home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 May: Tool Chest / Dev.CD May 97 TC.toast / Tool Chest / Interapplication Communication / AE Sample Applications / CoreSample 1.1 / CoreSample Source / CoreSample.c next >
Encoding:
Text File  |  1994-03-23  |  83.5 KB  |  2,285 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------//
  2. //    CoreSample  -      An application that is Apple Event-aware, Scripting Compatible,    //
  3. //                    and recordable. It supports the Required and Core Suite of         //
  4. //                    Apple Events, the Object Model, and the Open Scripting            //
  5. //                    Architecture.                                                    //
  6. //                                                                                    //
  7. //    by:    Sue Dumont                                                                    //
  8. //    Applications Scripting Group                                                    //
  9. //                                                                                    //
  10. //    Copyright © Apple Computer, Inc. 1991,1992                                        //
  11. //    All rights reserved.                                                            //
  12. //                                                                                    //
  13. //    SimpleSample                 1/1/92                                                //
  14. //    Version 1.0d6                 5/8/92                                                //
  15. //    Version 1.0.1                11/23/92                                            //
  16. //    Version 1.0.2                 4/2/93                                                //
  17. //    Version 1.1                    12/1/93                                                //
  18. //                                                                                    //
  19. //                                                                                    //
  20. //    NOTE:  This application conforms to the "Apple Event Registry, Standard Suites    //
  21. //    Winter 1992, Vers. 1.0".                                                        //                                                                                    //
  22. //                                                                                    //
  23. //    The main purpose of this sample code is to demonstrate how to develop an         //
  24. //    application that is Apple event-aware, scripting compatible, uses the Object    //
  25. //    Support Library, and supports Apple's Open Scripting Architecture.  In             //
  26. //    addition, it has its own 'aete' (Apple Event Terminology Extension) resource    //
  27. //    (CoreSampleAETE.r). By    incorporating these technologies into your application,    //
  28. //    your application will support Apple's Open Scripting Architecture.                //
  29. //                                                                                    //
  30. //    The functionality of CoreSample is basic window manipulation. The user may        //
  31. //    create, drag, size, zoom, and close windows.  All these actions    may be            //
  32. //    performed through Apple events.                                                    //
  33. //                                                                                    //
  34. //    This application is also "factored", which means that user interactions (such    //
  35. //    as dragging or sizing a window, selecting a menuitem) are converted into Apple    //
  36. //    events which the application sends off to itself, and then is handled by the    //
  37. //    corresponding event handler.  Factoring makes it possible to access the appli-    //
  38. //    cation's functionality through Apple events. It also makes it easier to record    //
  39. //    the user's actions in the form of Apple events.                                    //
  40. //                                                                                    //
  41. //    CoreSample supports the Required and Core suites of events, and the application    //
  42. //    and window object classes. One additional property has been added to the window //
  43. //    class, and that is its position, the top left-hand coordinates of the window.    //
  44. //    Some events only apply to the window class, such as Create, Move, Clone, and     //
  45. //    Set Data (application properties are not modifiable, except for pClipboard,     //
  46. //    which I do not support).  Currently, CoreSample supports the Simple Grammar,    //
  47. //    as defined in the "Object Support Library Developer Note".                        //
  48. //                                                                                    //
  49. //    The properties you may access with the Get Data Apple event are as follows:        //
  50. //        Application - Best Type, Default Type, Class, Name, IsFrontProcess, Version    //
  51. //        Window - Best Type, Default Type, Bounds, Class, Index, Name, Position,        //
  52. //                 Closeable, Titled, Resizable, Zoomable, Floating, Modal, Zoomed,    //
  53. //                 and Visible.                                                        //
  54. //    The properties you may set with the Set Data Apple event are as follows:        //
  55. //        Window - Bounds, Index, Zoomed, Name, Position, and Visible.                //
  56. //                                                                                    //
  57. //    When you create a new element, you may pass it initial data values. This        //
  58. //    application will create the    new element accordingly if either or both of the    //
  59. //    initial data parameters exist. In addition, with CoreSample, you may create or    //
  60. //    move a window without passing it an insertion location record. By default, a    //
  61. //    window will be created/moved to the frontmost position.                            //
  62. //                                                                                    //
  63. //    (NOTE: Some portions of this code are derived from TESample, a                    //
  64. //    sample application provided by Apple Developer Technical Support.)                //
  65. //                                                                                    //
  66. //                                                                                    //
  67. //    Modification History:                                                            //
  68. //    11/91      <smd>    -    Initial code implementation.                                //
  69. //    01/06/92  <kc>    -    Added code for Count Elements, Do Objects Exist, Move,        //
  70. //                        and Get Data Size.                                            //
  71. //    01/09/92  <kc>    -    Quick clean up for Scripting QuickStart.                    //
  72. //    01/10/92  <smd>    -    Made insertion location parameter optional in the Create     //
  73. //                        and Move events, and provided my own default behavior.        //
  74. //    01/21/92  <smd>    -    Positive and negative offset when referencing by index.      //
  75. //    01/30/92  <smd>    -    Adding complete support for core suite and properties.        //
  76. //    02/05/92  <smd>    -    Handling optional parameters in Create Element event.        //
  77. //    02/17/92  <smd>    -  Added InitializeDescs() and DisposeDescs() routines.            //
  78. //    02/21/92  <smd> -    Fixed bug where the same AEDesc was being passed as source    //
  79. //                        and dest to AECoerceDesc().                                    //
  80. //                     -    Send myself a Move event when user clicks in content of a    //
  81. //                        window.                                                        //
  82. //    02/24/92  <smd> -    Now sends a Move event when just making a window active.    //
  83. //                        This is done in the DoEvent routine, drag region.            //
  84. //    02/25/92  <smd> -    Modified GetWindowWithTitle, GetWidnowWithIndex, and        //
  85. //                        GetWindowIndexNum routines to use WindowList so ALL windows    //
  86. //                        will be accessed (even invisible ones).                        //
  87. //                     -    Changed InitializeDescs to MyInitDescs and DisposeDescs to    //
  88. //                        MyDisposeDescs.                                                //
  89. //                     -    Removed the FailIfErr calls from the AE Handlers so that    //
  90. //                        they will return the error code rather than dying.            //
  91. //    02/28/92  <smd> -    Added coercion routines (thanks Kevin) to clean up code.    //
  92. //                        These convert from descs to boolean, long, and pstrings.    //
  93. //    04/20/92  <smd> -  Fixed a bug with setting the visibility property of a window.//
  94. //    04/27/92  <smd>    -  Fixed bug in DoSetData where data was set to a pointer, and    //
  95. //                        then the pointer was diposed of.                            //
  96. //    04/30/92  <smd> -  Check if replacing the same window in HandleMove                //
  97. //                        (i.e., "move window 2 to window 2"). If so, do nothing.        //
  98. //    06/25/92  <smd> -    Changed FindRelativeWindow to return the windowPtr of the    //
  99. //                        window being replaced rather than closing it. This caused    //
  100. //                        an error when trying to replace the same window, in which    //
  101. //                        case nothing should happen. (Ex. move window 2 to window 2).//
  102. //    07/19/92  <smd>    -    Fixed bug where the Move event was not recording the        //
  103. //                        correct window being moved when the data was being passed    //
  104. //                        by index rather than by name.                                //
  105. //    10/01/92  <smd> -    Added pVersion to application and now set the port before    //
  106. //                        setting the pPosition property.                                //
  107. //     4/02.93  <smd>    -    added GetWindowBounds routine to calculate the correct         //
  108. //                        bounds when the bounds accessed from the content region is    //
  109. //                        invalid (such as when the application is hidden).            //
  110. //                    -    cleaned up the aete.                                        //
  111. //     6/22/93  <doo> -     converted files to run in the Think C 6.0 environment        //
  112. //                        Fixed incorrect comparison of rects and windowlist problems //
  113. //                        associated with the Think compiler.                            //
  114. //    12/1/93    <dan>    -    added PowerPC support - will run native on PowerPC if         //
  115. //                        compiled on PowerPC system.    These changes are denoted        //
  116. //                        by [pwpc].                                                    //
  117. //----------------------------------------------------------------------------------//
  118. #include    <SysEqu.h>                        // To use WindowList.
  119. #include    <Types.h>
  120. #include     <Quickdraw.h>
  121. #include     <Events.h>
  122. #include     <AppleEvents.h>
  123. #include     <AEObjects.h>
  124. #include     <AEPackObject.h>
  125. #include    <Resources.h>                    // for version resource
  126. #include     <Windows.h>
  127. #include     <Menus.h>
  128. #include     <Dialogs.h>
  129. #include     <Desk.h>
  130. #include     <Scrap.h>
  131. #include    <limits.h>
  132. #include     <ToolUtils.h>
  133. #include     <Memory.h>
  134. #include     <SegLoad.h>
  135. #include     <OSUtils.h>
  136. #include     <OSEvents.h>
  137. #include     <DiskInit.h>
  138. #include     <Packages.h>
  139. #include     <Traps.h>
  140. #include    <string.h>
  141. #include    <Strings.h>
  142. #include    <stdarg.h>
  143. #include    "AERegistry.h"                // Constants defined in the Registry.
  144. #include     "CoreSample.h"
  145.  
  146. #define HiWrd(aLong)    (((aLong) >> 16) & 0xFFFF)
  147. #define LoWrd(aLong)    ((aLong) & 0xFFFF)
  148.  
  149. typedef  long*            LongPtr;
  150. typedef  WindowPeek*    PeekPtr;
  151.  
  152.     //    Globals.
  153. SysEnvRec        gMac;                    // Contains the system environment
  154. Boolean            gHasWaitNextEvent;        // True if WaitNextEvent trap is available
  155. Boolean            gInBackground;            // Determines if currently in the background
  156. long            gNumWindowsOpen;        // The number of windows open
  157. short            gNewWindows;            // The number of new windows created
  158. Boolean            gQuitApp;                // True to quit the application
  159. AEDesc            gNullDesc;                // A null descriptor record
  160. AEAddressDesc    gSelfAddress;            // A self-addressed address descriptor record
  161. ProcessSerialNumber    gSelfPSN;            // This application's psn
  162. short            gRefNum;                // reference number of rescource file
  163.  
  164. #if powerc                // [pwpc]
  165. QDGlobals qd;
  166. #endif
  167.  
  168. //----------------------------------------------------------------------------------//
  169. //            PROTOTYPES                                                                //
  170. //----------------------------------------------------------------------------------//
  171. void        AdjustMenuStates(void);
  172. void        AlertUser(short error);
  173. void        CloseTheWindow(WindowPtr window);
  174. WindowPtr    CreateNewWindow(WindowPtr behind);
  175. OSErr        CreateWindowObjectSpec(WindowPtr window,short formType,AEDesc *objectSpec);
  176. void        DoEvent(EventRecord *event);
  177. void        DoGrowWindow(WindowPtr window, EventRecord *event);
  178. void        DoMenuCommand(long menuResult);
  179. OSErr         DoSetData(AEDesc *token, AEDesc *data);
  180. void        DoUpdate(WindowPtr window);
  181. void        EventLoop(void);
  182. void        FailIfErr(OSErr error);
  183. OSErr        FindRelativeWindow(WindowPtr *window,AEDesc *object,DescType pos,WindowPtr *replaceWindow);
  184. OSErr        GetAppData(DescType theProperty, AEDesc *result);
  185. OSErr        GetMissingParams(AppleEvent *theAppleEvent);
  186. OSErr        GetWindowData(DescType property, WindowPtr window, AEDesc *result);
  187. long        GetWindowIndexNum(WindowPtr window);
  188. WindowPtr    GetWindowAtIndex(long index);
  189. WindowPtr    GetWindowWithTitle(ConstStr255Param title);
  190. void        InitAEHandlers(void);
  191. void        Initialize(void);
  192. Boolean     IsAppWindow(WindowPtr window);
  193. Boolean     IsDAWindow(WindowPtr window);
  194. Boolean     IsTrapAvailable(short tNumber, TrapType tType);
  195. void        ReportError(AppleEvent *reply, long err);
  196. WindowPtr    ResolveToWindow(AEDesc *objectSpecifier);
  197. void        SendClose(WindowPtr  window);
  198. void        SendCreateElement(void);
  199. void        SendMoveEvent(WindowPtr windowToMove, long index);
  200. void        SendQuitApp(void);
  201. void         SendSetData(AEDesc *pDesc, AEDesc *pData, AEDesc *object);
  202. void        SetUpPropertyData(WindowPtr window,DescType propType,DescType dataType,Size dataSize);
  203. void        SignalError(short error);
  204. void        Terminate(void);
  205. void        ZoomIt(WindowPtr window, short part);
  206. Rect        GetWindowBounds(WindowPtr window);
  207.  
  208. extern pascal OSErr CreateObjSpecifier(DescType theClass, AEDesc *theContainer,
  209.                         DescType keyForm, AEDesc *keyData, Boolean disposeInputs, 
  210.                         AEDesc *objSpecifier);
  211. extern void _DataInit();
  212.  
  213.  
  214. //----------------------------------------------------------------------------------//
  215. #pragma segment Main
  216. main()
  217. {
  218. #ifndef THINK_C
  219.     UnloadSeg((Ptr) _DataInit);        // Note that _DataInit must not be in Main!
  220. #endif
  221.  
  222.     MaxApplZone();                    // Expand the heap so code segments load at the top.
  223.     Initialize();                    // Initialize the program
  224.     
  225. #ifndef THINK_C                        // Initialize the program
  226.     UnloadSeg((Ptr)Initialize);        // Note that Initialize must not be in Main!
  227. #endif
  228.  
  229.     EventLoop();                    // Call the main event loop
  230. }
  231.  
  232. //----------------------------------------------------------------------------------//
  233. // Continue retrieving events until the application terminates.                        //
  234. //----------------------------------------------------------------------------------//
  235. #pragma segment Main
  236. void EventLoop()
  237. {
  238.     RgnHandle        cursorRgn;
  239.     Boolean            gotEvent;
  240.     EventRecord        event;
  241.  
  242.     cursorRgn = NewRgn();
  243.     gQuitApp = false;                // This is set to true in Terminate().        
  244.     
  245.     while (!gQuitApp)                // Loop until user quits or error.
  246.     {
  247.         if (gHasWaitNextEvent)
  248.             gotEvent = WaitNextEvent(everyEvent, &event, LONG_MAX, cursorRgn);
  249.         else 
  250.         {
  251.             SystemTask();
  252.             gotEvent = GetNextEvent(everyEvent, &event);
  253.         }
  254.         if (gotEvent)
  255.             DoEvent(&event);
  256.     }
  257. }
  258.  
  259. //----------------------------------------------------------------------------------//
  260. //    Find out which event this is and send it off to its appropriate handler.        //
  261. //    When the user clicks in the drag region, either one of two events may be        //
  262. //    triggered. The set position property (set data event) would occur if the widnow //
  263. //    is dragged to another location, or the move event would be sent if the window    //
  264. //    is just made active. In the latter case, the window's index before being        //
  265. //    moved to the front is passed to SendMoveEvent for recording purposes.            //
  266. //----------------------------------------------------------------------------------//
  267. #pragma segment Main
  268. void DoEvent( EventRecord*  event )
  269. {
  270.     long        index=0;
  271.     short        part, err;
  272.     WindowPtr    window;
  273.     char        key;
  274.     Rect        bounds1, bounds2;
  275.     Point        aPoint;
  276.  
  277.     switch (event->what)
  278.     {
  279.         case mouseDown:
  280.             part = FindWindow(event->where, &window);
  281.             switch (part) 
  282.             {
  283.                 case inMenuBar:
  284.                     AdjustMenuStates();            
  285.                     DoMenuCommand(MenuSelect(event->where));
  286.                     break;
  287.                     
  288.                 case inSysWindow:
  289.                     SystemClick(event, window);
  290.                     break;
  291.                     
  292.                 case inContent:
  293.                     if (window != FrontWindow()) 
  294.                         SendMoveEvent(window, index);
  295.                     break;
  296.                     
  297.                 case inDrag:
  298.                     index = GetWindowIndexNum(window);
  299.                     bounds1 = (*((WindowPeek)window)->contRgn)->rgnBBox;
  300.                     DragWindow(window, event->where, &qd.screenBits.bounds);
  301.                     bounds2 = (*((WindowPeek)window)->contRgn)->rgnBBox;
  302.                     if ((bounds1.left == bounds2.left) && 
  303.                             (bounds1.top == bounds2.top))
  304.                         SendMoveEvent(GetWindowAtIndex(index), index);
  305.                     else
  306.                         SetUpPropertyData(window,pPosition,typeQDPoint,sizeof(Point));
  307.                     break;
  308.                     
  309.                 case inGoAway:
  310.                     if (TrackGoAway(window, event->where))
  311.                         SendClose(window);
  312.                     break;
  313.                     
  314.                 case inGrow:
  315.                     DoGrowWindow(window, event);
  316.                     break;
  317.                     
  318.                 case inZoomIn:                            // For recording purposes, we send an Apple
  319.                 case inZoomOut:                            // event to ourselves to set the bounds property.
  320.                     if (TrackBox(window, event->where, part))
  321.                     {
  322.                         ZoomIt(window, part);
  323.                         SetUpPropertyData(window, pIsZoomed, typeBoolean, sizeof(Boolean));
  324.                     }
  325.                     break;
  326.             }
  327.             break;
  328.             
  329.         case keyDown:
  330.         case autoKey:                               // Only handle menu key equivalents
  331.             key = event->message & charCodeMask;
  332.             if (event->modifiers & cmdKey)        // Command key down
  333.             {
  334.                 if (event->what == keyDown) 
  335.                 {
  336.                     AdjustMenuStates();                // Enable/disable/check menu items properly
  337.                     DoMenuCommand(MenuKey(key));
  338.                 }
  339.             } 
  340.             break;
  341.             
  342.         case activateEvt:
  343.             DrawGrowIcon((WindowPtr)event->message);
  344.             break;
  345.             
  346.         case updateEvt:
  347.             DoUpdate((WindowPtr) event->message);
  348.             break;
  349.             
  350.         case diskEvt:
  351.             if (HiWord(event->message) != noErr)
  352.             {
  353.                 SetPt(&aPoint, kDILeft, kDITop);
  354.                 err = DIBadMount(aPoint, event->message);
  355.             }
  356.             break;
  357.             
  358.         case kOSEvent:
  359.             {
  360.                 switch ((event->message >> 24) & 0x0FF)            // High byte of message.
  361.                 {
  362.                     case kMouseMovedMessage:
  363.                         break;                        // Do nothing if mouse moved.
  364.                     
  365.                     case kSuspendResumeMessage:        // suspend/resume is also an activate/deactivate
  366.                         SetCursor(&qd.arrow);
  367.                         if (IsAppWindow(window = FrontWindow()))
  368.                             DrawGrowIcon(window);
  369.                         break;
  370.                 }
  371.             }
  372.             break;
  373.             
  374.         case kHighLevelEvent:                        // Let the Apple Event Manager handle high level event.
  375.             AEProcessAppleEvent(event);
  376.             break;
  377.  
  378.         default:
  379.             break;
  380.     }
  381. }
  382.  
  383. //----------------------------------------------------------------------------------//
  384. //    Handle the mouseDown event in the grow box region of the window.  If the         //
  385. //    window has been resized, an Apple Event is sent to set the bounds property.        //
  386. //    This is done for recording purposes.                                            //
  387. //----------------------------------------------------------------------------------//
  388. #pragma segment Main
  389. void DoGrowWindow(    WindowPtr     window,
  390.                     EventRecord* event    )
  391. {
  392.     long            result;
  393.     Rect            tempRect;
  394.  
  395.     tempRect = qd.screenBits.bounds;        // Set up the limiting values.
  396.     tempRect.top = kMinWinDim;
  397.     tempRect.left = kMinWinDim;
  398.     result = GrowWindow(window, event->where, &tempRect);
  399.     if (result)                            // Did window actually change size?
  400.     {
  401.         SetPort(window);
  402.         InvalRect(&window->portRect);
  403.         SizeWindow(window, LoWrd(result), HiWrd(result), true);
  404.         InvalRect(&window->portRect);        // Send event for recording purposes.
  405.         SetUpPropertyData(window, pBounds, typeQDRectangle, sizeof(Rect));
  406.     }
  407. }
  408.  
  409. //----------------------------------------------------------------------------------//
  410. //    Zoom the window and set the refcon field to reflect its zoomed state.            //
  411. //----------------------------------------------------------------------------------//
  412. #pragma segment Main
  413. void ZoomIt( WindowPtr    window,
  414.              short        part  )
  415. {
  416.     SetPort(window);
  417.     EraseRect(&window->portRect);            // We just have a blank window.
  418.     ZoomWindow(window, part, window == FrontWindow());
  419.     SetWRefCon(window, (long)part == inZoomOut);    // Set to true if zoomed.
  420.     InvalRect(&window->portRect);
  421. }
  422.  
  423. //----------------------------------------------------------------------------------//
  424. //    This is called when an update event is received for a window.                    //
  425. //----------------------------------------------------------------------------------//
  426. #pragma segment Main
  427. void DoUpdate( WindowPtr  window )
  428. {
  429.     if (IsAppWindow(window)) 
  430.     {
  431.         BeginUpdate(window);
  432.         SetPort(window);
  433.         EraseRect(&window->portRect);            // We just have an empty window.
  434.         DrawGrowIcon(window);
  435.         EndUpdate(window);
  436.     }
  437. }
  438.  
  439. //----------------------------------------------------------------------------------//
  440. //    Set up the menus according to the current state.                                //
  441. //----------------------------------------------------------------------------------//
  442. #pragma segment Main
  443. void AdjustMenuStates()
  444. {
  445.     WindowPtr        window;
  446.     MenuHandle        menu;
  447.  
  448.     window = FrontWindow();
  449.     menu = GetMHandle(mFile);
  450.     if (gNumWindowsOpen < kMaxOpenWindows)
  451.         EnableItem(menu, iNew);            // Enable New if we can open more windows.
  452.     else
  453.         DisableItem(menu, iNew);
  454.     if (window)
  455.         EnableItem(menu, iClose);        // Enable Close if there is a window to close.
  456.     else
  457.         DisableItem(menu, iClose);
  458. }
  459.  
  460. //----------------------------------------------------------------------------------//
  461. //    This is called when an item is chosen from the menu bar.                        //
  462. //----------------------------------------------------------------------------------//
  463. #pragma segment Main
  464. void DoMenuCommand(long  menuResult)
  465. {
  466.     short        menuID, menuItem;
  467.     short        itemHit, daRefNum;
  468.     Str255        daName;
  469.     WindowPtr    window;
  470.  
  471.     window = FrontWindow();
  472.     menuID = HiWord(menuResult);
  473.     menuItem = LoWord(menuResult);
  474.     switch (menuID)
  475.     {
  476.         case mApple:
  477.             switch (menuItem) 
  478.             {
  479.                 case iAbout:
  480.                     itemHit = Alert(rAboutAlert, nil);
  481.                     break;
  482.                 default:            // all other items in this menu are DA's.
  483.                     GetItem(GetMHandle(mApple), menuItem, daName);
  484.                     daRefNum = OpenDeskAcc(daName);
  485.                     break;
  486.             }
  487.             break;
  488.             
  489.         case mFile:
  490.             switch (menuItem)                // All these items send Apple events to
  491.             {                                // handle the selection.
  492.                 case iNew:
  493.                     SendCreateElement();
  494.                     break;
  495.                 case iClose:
  496.                     SendClose(FrontWindow());
  497.                     break;
  498.                 case iQuit:
  499.                     SendQuitApp();
  500.                     break;
  501.             }
  502.             break;
  503.         
  504.         case mEdit:                    // Call SystemEdit for DA editing & MultiFinder.
  505.             SystemEdit(menuItem-1);
  506.             break;
  507.     }
  508.     HiliteMenu(0);                    // Unhighlight what MenuSelect (or MenuKey) hilited.
  509. }
  510.  
  511. //----------------------------------------------------------------------------------//
  512. //    This routine appends the ascii representation of num to the title string.        //
  513. //----------------------------------------------------------------------------------//
  514. #pragma segment Main
  515. void MakeNewWindowTitle( short        num,                // Window number.
  516.                          Str255        title)                // Window title.
  517. {
  518.     short        i, count, index;
  519.     char        numStr[5];
  520.     
  521.     i = 0;
  522.     do {
  523.             numStr[i++] = num % 10 + '0';
  524.         } while (num /= 10);
  525.         
  526.     index = title[0] + 1;                    // Get length of title string.
  527.     
  528.     for (count = i-1; count >= 0; count--)
  529.         title[index++] = numStr[count];
  530.     title[0] += i;
  531. }        
  532.  
  533. //----------------------------------------------------------------------------------//
  534. //    Create a new window behind the given window.  Use the window's refCon            //
  535. //    field to indicate whether the window is zoomed or not.                            //
  536. //----------------------------------------------------------------------------------//
  537. #pragma segment Main
  538. WindowPtr CreateNewWindow(WindowPtr behindWindow)
  539. {
  540.     Ptr            storage;
  541.     WindowPtr    newWindow, firstWindow;
  542.     Rect        bounds;
  543.     Str255        title;
  544.  
  545.     if (gNumWindowsOpen < kMaxOpenWindows)
  546.     {
  547.         storage = NewPtr(sizeof(WindowRecord));
  548.         if (storage != nil) 
  549.         {
  550.             newWindow = GetNewWindow(rDocWindow, storage, behindWindow);
  551.             if (newWindow != nil)
  552.             {
  553.                 gNumWindowsOpen++;            // Increment the number of windows currently open.
  554.                 gNewWindows++;                // Increment the number of new windows created.
  555.                 GetWTitle(newWindow, title);
  556.                 MakeNewWindowTitle(gNewWindows, title);
  557.                 SetWTitle(newWindow, title);
  558.                 if (firstWindow = FrontWindow())
  559.                 {
  560.           //•••            bounds = (*((WindowPeek)firstWindow)->contRgn)->rgnBBox;
  561.                     bounds = GetWindowBounds(firstWindow);
  562.                     MoveWindow(newWindow, bounds.left+30, bounds.top+30, false);
  563.                 }
  564.                 SetWRefCon(newWindow, 0L);            // set zoom state to false.
  565.                 SetPort(newWindow);
  566.                 return(newWindow);
  567.             }
  568.         else
  569.             DisposPtr(storage);        // Dispose of the storage if it is not used.
  570.         }
  571.     }
  572.     return(nil);
  573. }
  574.  
  575. //----------------------------------------------------------------------------------//
  576. //    Close the given window or desk accessory.                                        //
  577. //----------------------------------------------------------------------------------//
  578. #pragma segment Main
  579. void CloseTheWindow(WindowPtr  window)
  580. {
  581.     if (IsDAWindow(window))
  582.         CloseDeskAcc(((WindowPeek)window)->windowKind);
  583.     else 
  584.         if (IsAppWindow(window))
  585.         {
  586.             CloseWindow(window);
  587.             DisposPtr((Ptr)window);
  588.             gNumWindowsOpen--;
  589.         }
  590. }
  591.  
  592. //----------------------------------------------------------------------------------//
  593. //    Returns true if the window belongs to this application, else false.                //
  594. //----------------------------------------------------------------------------------//
  595. #pragma segment Main
  596. Boolean IsAppWindow(WindowPtr  window)
  597. {
  598.     if (!window)
  599.         return(false);
  600.     else 
  601.         return(((WindowPeek)window)->windowKind == userKind);
  602. }
  603.  
  604. //----------------------------------------------------------------------------------//
  605. //    Returns true if the given window belongs to a DA, else false is returned.        //
  606. //----------------------------------------------------------------------------------//
  607. #pragma segment Main
  608. Boolean IsDAWindow(WindowPtr  window)
  609. {
  610.     if (window == nil)
  611.         return(false);
  612.     else                    // DA windows have negative windowKinds.
  613.         return(((WindowPeek)window)->windowKind < 0);
  614. }
  615.  
  616. //----------------------------------------------------------------------------------//
  617. //  If an error has occurred, I check the user interaction level. If I can            //
  618. //    interact with the user, I put up a dialog and exit the application; otherwise,    //
  619. //    I just exit the application.                                                    //
  620. //                                                                                    //
  621. //    ***NOTE: Real applications would not handle errors in this fashion!  If they    //
  622. //    cannot interact with the user, they should abort the Apple event handler and    //
  623. // return the error in the reply parameter.                                            //
  624. //----------------------------------------------------------------------------------//
  625. #pragma segment    Main
  626. void FailIfErr(OSErr  error)
  627. {
  628.     if (error)
  629.     {
  630.         if (!(AEInteractWithUser(kNoTimeOut, nil, nil)))            // Can we interact?
  631.             AlertUser(eAEError);                                    // Yes, so put up the dialog.
  632.         ExitToShell();
  633.     }
  634. }
  635.  
  636. //----------------------------------------------------------------------------------//
  637. //    Display an alert for the user to indicate that an error has occurred.            //
  638. //----------------------------------------------------------------------------------//
  639. #pragma segment Main
  640. void AlertUser(short  error)
  641. {
  642.     short        itemHit;
  643.     Str255        message;
  644.  
  645.     GetIndString(message, kErrStrings, error);
  646.     ParamText(message, (ConstStr255Param)"\p", (ConstStr255Param)"\p", (ConstStr255Param)"\p");    // [pwpc]
  647.     itemHit = Alert(rUserAlert, nil);
  648. }
  649.  
  650. //----------------------------------------------------------------------------------//
  651. //    Quit the application by closing all windows and setting the quit flag to true.    //
  652. //----------------------------------------------------------------------------------// 
  653. #pragma segment Main
  654. void Terminate()
  655. {
  656.     WindowPtr    aWindow;
  657.  
  658.     while(aWindow = FrontWindow())
  659.         CloseTheWindow(aWindow);
  660.       AEDisposeDesc(&gSelfAddress);            // Dispose of my self-addressed descriptor.
  661.     gQuitApp = true;
  662. }
  663.  
  664. //----------------------------------------------------------------------------------//
  665. //    Perform the initialization necessary at start-up time.  Note that we use        //
  666. //    kCurrentProcess in our psn rather than calling GetCurrentProcess.  Using        //
  667. //    kCurrentProcess will allow us to record those events we send to ourselves,        //
  668. //    otherwise, the recorder won't recognize the psn and won't record our event!        //
  669. //----------------------------------------------------------------------------------//
  670. #pragma segment Initialize
  671. void Initialize()
  672. {
  673.     Handle                    menuBar;
  674.     long                    total, contig;
  675.     EventRecord             event;
  676.     short                    count;
  677.  
  678.     gInBackground = false;
  679.     InitGraf((Ptr)&qd.thePort);
  680.     InitWindows();
  681.     InitMenus();
  682.     InitDialogs(nil);
  683.     InitCursor();
  684.     InitAEHandlers();
  685.     for (count = 1; count <= 3; count++)
  686.         EventAvail(everyEvent, &event);
  687.      
  688.     SysEnvirons(kSysEnvironsVersion, &gMac);    
  689.     if (gMac.machineType < 0) 
  690.         SignalError(eWrongMachine);                // Less than 128K ROM's.
  691.     gHasWaitNextEvent = IsTrapAvailable(_WaitNextEvent, ToolTrap);
  692.      
  693.     if ((long)GetApplLimit() - (long)ApplicZone() < kMinHeap) 
  694.         SignalError(eSmallSize);
  695.     
  696.     PurgeSpace(&total, &contig);
  697.     if (total < kMinSpace)
  698.         if (UnloadScrap() != noErr)
  699.             SignalError(eNoMemory);
  700.         else
  701.         {
  702.             PurgeSpace(&total, &contig);
  703.             if (total < kMinSpace)
  704.                 SignalError(eNoMemory);
  705.         }
  706.  
  707.     if (!(menuBar = GetNewMBar(rMenuBar)))        // Set up menu bar.
  708.         SignalError(eNoMemory);
  709.     SetMenuBar(menuBar);
  710.     DisposHandle(menuBar);
  711.     AddResMenu(GetMHandle(mApple), 'DRVR');            // Add DA's to menu.
  712.     DrawMenuBar();
  713.  
  714.         // Set up the self-addressed descriptor record.
  715.       gSelfPSN.highLongOfPSN = 0;
  716.       gSelfPSN.lowLongOfPSN = kCurrentProcess;        //* Use this instead of GetCurrentProcess *//
  717.       FailIfErr(AECreateDesc(typeProcessSerialNumber,(Ptr)&gSelfPSN,sizeof(ProcessSerialNumber),&gSelfAddress));
  718.     gNullDesc.descriptorType = typeNull;        // Initialize the global null descriptor record.
  719.     gNullDesc.dataHandle = nil;
  720.  
  721.     gRefNum = CurResFile();
  722.     gNumWindowsOpen = 0;
  723.     gNewWindows = 0;
  724. }
  725.  
  726. //----------------------------------------------------------------------------------//
  727. //    Returns true if the given trap number is implemented, else returns false.        //
  728. //----------------------------------------------------------------------------------//
  729. #pragma segment Initialize
  730. Boolean IsTrapAvailable(short trapNum, TrapType  tType)
  731. {
  732.     if ((tType == (unsigned char)ToolTrap) && (gMac.machineType > envMachUnknown) &&
  733.          (gMac.machineType < envMacII))
  734.     {                                            // it's a 512K, Plus, or SE
  735.         trapNum = trapNum & 0x03FF;
  736.         if (trapNum > 0x01FF)                    // which means the tool traps
  737.             trapNum = _Unimplemented;            // only go to 0x01FF
  738.     }
  739.     return(NGetTrapAddress(trapNum, tType) != GetToolTrapAddress(_Unimplemented));    // [pwpc]
  740. }
  741.  
  742. //----------------------------------------------------------------------------------//
  743. #pragma segment Initialize
  744. void SignalError(short error)
  745. {
  746.     AlertUser(error);
  747.     ExitToShell();
  748. }
  749.  
  750. //**********************************************************************************//
  751. //                    *  Apple Events and Object Model Support *                        //
  752. //**********************************************************************************//
  753.  
  754. //----------------------------------------------------------------------------------//
  755. //    Initializes all descriptor records passed in to this routine.  The variable        //
  756. //    argument list is null terminated.                                                //
  757. //----------------------------------------------------------------------------------//
  758. #pragma segment Main
  759. void MyInitDescs(AEDesc*  desc1, ... )            // Variable, null terminated argument list.
  760. {
  761.     va_list        argptr;                            // pointer to each argument in list.
  762.     AEDesc*        nextDesc;                        // next descriptor argument in list.
  763.  
  764.     va_start(argptr, desc1);
  765.     desc1->descriptorType = typeNull;
  766.     desc1->dataHandle = nil;
  767.     
  768.     while(nextDesc = va_arg(argptr, AEDesc *))
  769.     {
  770.         nextDesc->descriptorType = typeNull;
  771.         nextDesc->dataHandle = nil;
  772.     }
  773.     va_end(argptr);
  774. }
  775.     
  776. //----------------------------------------------------------------------------------//
  777. //    Dispose all descriptor records passed into this routine. (Variable arg. list).    //
  778. //----------------------------------------------------------------------------------//
  779. #pragma segment Main
  780. void MyDisposeDescs(AEDesc*  desc1, ... )        // Null terminated argument list.
  781. {
  782.     va_list        argptr;            // pointer to each argument in list.
  783.     AEDesc*        nextDesc;        // descriptor argument in list.
  784.  
  785.     va_start(argptr, desc1);
  786.     if (desc1->dataHandle)
  787.         AEDisposeDesc(desc1);
  788.  
  789.     while(nextDesc = va_arg(argptr, AEDesc *))
  790.     {
  791.         if (nextDesc->dataHandle)
  792.             AEDisposeDesc(nextDesc);
  793.     }
  794.     va_end(argptr);
  795. }
  796.  
  797. //----------------------------------------------------------------------------------//
  798. //    Converts a descriptor to a boolean.                                                //
  799. //----------------------------------------------------------------------------------//
  800. #pragma segment AppleEvents
  801. OSErr DescToBoolean(const AEDesc* desc, Boolean* boolvalue)
  802. {
  803.     AEDesc            tempDesc;
  804.     Handle            dataHandle;
  805.  
  806.     tempDesc.dataHandle = nil;
  807.     if (desc->descriptorType == typeBoolean)
  808.         dataHandle = desc->dataHandle;
  809.     else
  810.         if (AECoerceDesc(desc, typeBoolean, &tempDesc) == noErr)
  811.             dataHandle = tempDesc.dataHandle;
  812.         else
  813.             return(errAECoercionFail);
  814.     
  815.     *boolvalue = **dataHandle;
  816.     MyDisposeDescs(&tempDesc, kEndOfList);
  817.     return(noErr);
  818. }
  819.  
  820. //----------------------------------------------------------------------------------//
  821. //    Converts a descriptor to a long.                                                //
  822. //----------------------------------------------------------------------------------//
  823. #pragma segment AppleEvents
  824. OSErr DescToLong(const  AEDesc* desc, long* longvalue)
  825. {
  826.     AEDesc            tempDesc;
  827.     Handle            dataHandle;
  828.  
  829.     tempDesc.dataHandle = nil;
  830.     if (desc->descriptorType == typeLongInteger)
  831.         dataHandle = desc->dataHandle;
  832.     else
  833.         if (AECoerceDesc(desc, typeLongInteger, &tempDesc) == noErr)
  834.             dataHandle = tempDesc.dataHandle;
  835.         else
  836.             return(errAECoercionFail);
  837.     
  838.     *longvalue = *(LongPtr)*dataHandle;
  839.     MyDisposeDescs(&tempDesc, kEndOfList);
  840.     return(noErr);
  841. }
  842.  
  843. //----------------------------------------------------------------------------------//
  844. //    Converts a descriptor to a pascal string.                                        //
  845. //----------------------------------------------------------------------------------//
  846. #pragma segment AppleEvents
  847. OSErr DescToPString(const AEDesc* desc, Str255 str, short maxLength)
  848. {
  849.     AEDesc            tempDesc;
  850.     Handle            dataHandle;
  851.     long            charCount;
  852.  
  853.     tempDesc.dataHandle = nil;
  854.     if (desc->descriptorType == typeChar)
  855.         dataHandle = desc->dataHandle;
  856.     else
  857.         if (AECoerceDesc(desc, typeChar, &tempDesc) == noErr)
  858.             dataHandle = tempDesc.dataHandle;
  859.         else
  860.             return(errAECoercionFail);
  861.     
  862.     charCount = GetHandleSize(dataHandle);
  863.     if (charCount > maxLength)
  864.     {
  865.         MyDisposeDescs(&tempDesc, kEndOfList);
  866.         return(errAECoercionFail);
  867.     }
  868.  
  869.     str[0] = charCount;
  870.     HLock(dataHandle);
  871.     BlockMove(*dataHandle, &str[1], charCount);
  872.     HUnlock(dataHandle);        // This may be from desc, so must unlock.
  873.     MyDisposeDescs(&tempDesc, kEndOfList);
  874.     return(noErr);
  875. }
  876.  
  877. //----------------------------------------------------------------------------------//
  878. //    Create the first window in response to the Open Application Apple Event.        //
  879. //----------------------------------------------------------------------------------//
  880. #pragma segment Main
  881. pascal
  882. OSErr HandleOpenApp(AppleEvent *theAppleEvent, AppleEvent* reply, long refCon)
  883. {
  884.     #pragma unused (reply,refCon)
  885.     WindowPtr    window;
  886.     OSErr        err;
  887.     
  888.     if (!(err = GetMissingParams(theAppleEvent)))        // Error if any parameters.
  889.     {
  890.         if (window = CreateNewWindow((WindowPtr)-1))    // Create initial window
  891.             ShowWindow(window);
  892.         else
  893.             err = errAEEventNotHandled;
  894.     }
  895.     return(err);
  896. }
  897.  
  898. //----------------------------------------------------------------------------------//
  899. //    Send a Quit Application Apple Event to myself to terminate this app.            //
  900. //----------------------------------------------------------------------------------//
  901. #pragma segment Main
  902. void SendQuitApp()
  903. {
  904.     AppleEvent    myAppleEvent, reply;
  905.     
  906.         //    Create the Apple Event.
  907.     FailIfErr(AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &gSelfAddress,
  908.                                     kAutoGenerateReturnID, kAnyTransactionID, &myAppleEvent));
  909.         //    Send the Apple Event.
  910.       FailIfErr(AESend(&myAppleEvent, &reply, kAENoReply+kAENeverInteract, kAENormalPriority,
  911.                                 kAEDefaultTimeout, nil, nil));
  912.       AEDisposeDesc(&myAppleEvent);                // Dispose of the Apple Event.
  913. }
  914.  
  915. //----------------------------------------------------------------------------------//
  916. //    Quit the application.                                                            //
  917. //----------------------------------------------------------------------------------//
  918. #pragma segment Main
  919. pascal
  920. OSErr HandleQuitApp(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  921. {
  922.     #pragma unused (reply,refCon)
  923.     OSErr    err;
  924.     
  925.     if (!(err = GetMissingParams(theAppleEvent)))    // Error if there are any parameters.
  926.         Terminate();
  927.     return(err);
  928. }
  929.  
  930. //----------------------------------------------------------------------------------//
  931. //    This routine makes a clone of the given window by copying its bounds, zoom        //
  932. //    state, and title (with the addition of "copy") properties.                        //
  933. //----------------------------------------------------------------------------------//
  934. #pragma segment Main
  935. WindowPtr CloneWindow(WindowPtr windowToClone, WindowPtr behindWindow)
  936. {
  937.     WindowPtr    clonedWindow;
  938.     Rect        bounds;
  939.     Str255        title;
  940.  
  941.     if (clonedWindow = CreateNewWindow(behindWindow))
  942.     {
  943.         GetWTitle(windowToClone, title);
  944.         p2cstr(title);
  945.         strcat((char *)title, " copy\0");
  946.         c2pstr((char *)title);
  947.         bounds = GetWindowBounds(windowToClone);
  948.         SetWTitle(clonedWindow, title);
  949.         MoveWindow(clonedWindow, bounds.left, bounds.top, false);
  950.         SizeWindow(clonedWindow, bounds.right-bounds.left, bounds.bottom-bounds.top, true);
  951.         SetWRefCon(clonedWindow, GetWRefCon(windowToClone));
  952.         return(clonedWindow);
  953.     }
  954.     return(nil);
  955. }
  956.  
  957. //----------------------------------------------------------------------------------//
  958. //    Handle the Clone Apple Event and create a clone of the given object. To clone    //
  959. //    a window, I clone its bounds, zoom state, and visible properties. In addition,    //
  960. //    I clone the window's title and append " copy" to it for the cloned window's        //
  961. //    title. If the insertion location parameter is not in the event record, I         //
  962. //    perform the default behavior, which is to position the clone behind the         //
  963. //    window being cloned.                                                            //
  964. //----------------------------------------------------------------------------------//
  965. #pragma segment Main
  966. pascal
  967. OSErr HandleClone(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  968. {
  969.     #pragma unused (refCon)
  970.     AEDesc        cloneObject, windowObject, replyObject, insertionLoc;
  971.     AERecord    insertionRec;
  972.     DescType    theType, position;
  973.     WindowPtr    windowToClone, window, rplcWindow, behindWindow = nil;
  974.     Size        paramSize;
  975.     OSErr        err = noErr;
  976.  
  977.  
  978.     MyInitDescs(&cloneObject,&windowObject,&replyObject,&insertionLoc,&insertionRec,kEndOfList);
  979.         //    Let's get the direct object, the object to clone.
  980.     if (err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeObjectSpecifier, &cloneObject))
  981.         goto myExit;
  982.     if (!(windowToClone = ResolveToWindow(&cloneObject)))
  983.     {
  984.         err = errAENoSuchObject;
  985.         goto myExit;
  986.     }
  987.     else        // we have a window to clone.
  988.     {
  989.         if (!(err = AEGetParamDesc(theAppleEvent,keyAEInsertHere,typeInsertionLoc,&insertionLoc)))
  990.             if (!(err = AECoerceDesc(&insertionLoc, typeAERecord, &insertionRec)))
  991.                 // Get object as typeWildCard because it may be null or an object specifier.
  992.                 if (!(err = AEGetKeyDesc(&insertionRec, keyAEObject, typeWildCard, &windowObject)))
  993.                     if (!(err = AEGetKeyPtr(&insertionRec,keyAEPosition,typeEnumeration,&theType,
  994.                                         (Ptr)&position,sizeof(DescType),¶mSize)))
  995.                         err = FindRelativeWindow(&behindWindow, &windowObject, position, &rplcWindow);
  996.  
  997.         if (err)
  998.             if (err == errAEDescNotFound)
  999.                 behindWindow = windowToClone;        // Registry's default behavior.
  1000.             else
  1001.                 goto myExit;
  1002.     }
  1003.  
  1004.     if (window = CloneWindow(windowToClone, behindWindow))
  1005.     {
  1006.         if (((WindowPeek)windowToClone)->visible)
  1007.             ShowWindow(window);
  1008.         if (position == kAEReplace)
  1009.             CloseTheWindow(rplcWindow);
  1010.  
  1011.         if (reply->dataHandle != nil)
  1012.         {
  1013.             CreateWindowObjectSpec(window, kIndexKeyForm, &replyObject);
  1014.             err = AEPutParamDesc(reply, keyAEResult, &replyObject);
  1015.         }
  1016.     }
  1017.     else
  1018.         err = errAEEventNotHandled;
  1019.  
  1020. myExit:
  1021.     MyDisposeDescs(&cloneObject,&windowObject,&replyObject,&insertionLoc,&insertionRec,kEndOfList);
  1022.     return(err);
  1023. }    
  1024.  
  1025. //----------------------------------------------------------------------------------//
  1026. //    Send a Close Apple Event to myself to close the specified window.                //
  1027. //----------------------------------------------------------------------------------//
  1028. #pragma segment Main
  1029. void SendClose(WindowPtr  window)
  1030. {
  1031.     AppleEvent        myAppleEvent, reply;
  1032.     AEDesc            windowObject;                // The window object specifier.
  1033.  
  1034.                 //    Create the Close Apple Event.
  1035.     FailIfErr(AECreateAppleEvent(kAECoreSuite, kAEClose, &gSelfAddress, kAutoGenerateReturnID,
  1036.                                     kAnyTransactionID, &myAppleEvent));
  1037.                 //    Create the window object specifier and add this to myAppleEvent.
  1038.     CreateWindowObjectSpec(window, kIndexKeyForm, &windowObject);
  1039.     FailIfErr(AEPutParamDesc(&myAppleEvent, keyDirectObject, &windowObject));
  1040.                 //    Send the Apple Event.
  1041.       FailIfErr(AESend(&myAppleEvent, &reply, kAENoReply+kAECanInteract, kAENormalPriority,
  1042.                                 kAEDefaultTimeout, nil, nil));
  1043.                 //    Now dispose of the AppleEvent and object specifier.                                
  1044.       AEDisposeDesc(&myAppleEvent);
  1045.     AEDisposeDesc(&windowObject);
  1046. }
  1047.  
  1048. //----------------------------------------------------------------------------------//
  1049. //    Respond to the Close Apple Event by closing the specified window object.        //
  1050. //----------------------------------------------------------------------------------//
  1051. #pragma segment Main
  1052. pascal
  1053. OSErr HandleClose(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  1054. {
  1055.     #pragma unused (reply,refCon)
  1056.     AEDesc            windowObject;
  1057.     WindowPtr        windowToClose;
  1058.     OSErr            myErr;
  1059.     
  1060.     MyInitDescs(&windowObject,kEndOfList);
  1061.         //    First, get the direct object which is the object to close.
  1062.     myErr = AEGetParamDesc(theAppleEvent,keyDirectObject,typeObjectSpecifier,&windowObject);
  1063.     if (!myErr && !(myErr = GetMissingParams(theAppleEvent)))
  1064.     {
  1065.         if (windowToClose = ResolveToWindow(&windowObject))
  1066.             CloseTheWindow(windowToClose);
  1067.         else
  1068.             myErr = errAENoSuchObject;
  1069.     }
  1070.     MyDisposeDescs(&windowObject,kEndOfList);
  1071.     return(myErr);
  1072. }
  1073.  
  1074. //----------------------------------------------------------------------------------//
  1075. //    Respond to the Count Elements Apple Event.                                        //
  1076. //----------------------------------------------------------------------------------//
  1077. #pragma segment Main
  1078. pascal
  1079. OSErr HandleCountElements(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  1080. {
  1081.     #pragma unused (refCon)
  1082.     AEDesc            directObject;
  1083.     DescType        theType, theClass;
  1084.     Size            paramSize;
  1085.     OSErr            err;
  1086.     
  1087.  
  1088.     MyInitDescs(&directObject, kEndOfList);
  1089.         //    Get the direct object, should be null.
  1090.     if (!(err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeWildCard, &directObject)))
  1091.         if (!(err = AEGetParamPtr(theAppleEvent,keyAEObjectClass,typeType,&theType,(Ptr)&theClass,
  1092.                     sizeof(DescType),¶mSize)))        // Get class of elements to count.
  1093.             err = GetMissingParams(theAppleEvent);        // Error if more parameters.
  1094.  
  1095.     if (err)
  1096.         goto myExit;
  1097.         
  1098.         //    If we had a deeper object hierarchy, we'd probably call AEResolve here, but...
  1099.         //    we only handle the window class contained within the null object.
  1100.     if (theClass == cWindow && directObject.descriptorType == typeNull)
  1101.         err = AEPutParamPtr(reply, keyAEResult, typeLongInteger, (Ptr)&gNumWindowsOpen, sizeof(long));
  1102.  
  1103. myExit:
  1104.     MyDisposeDescs(&directObject, kEndOfList);
  1105.     return(err);
  1106. }
  1107.  
  1108. //----------------------------------------------------------------------------------//
  1109. //    Send a Create Element Apple Event to myself to create a new window. By default, //
  1110. //    I am setting the position to the beginning of the null container (frontmost).    //
  1111. //    In this case, as well as at the end of the container, the object parameter is    //
  1112. //    the null container. If the position is before, after, or replace, the object    //
  1113. //    parameter must be an object specifier to indicate the relative window.            //
  1114. //----------------------------------------------------------------------------------//
  1115. #pragma segment Main
  1116. void SendCreateElement()
  1117. {
  1118.     AppleEvent        myAppleEvent, reply;
  1119.     AERecord        insertionRec;                    // Insertion Loc record.
  1120.     AEDesc            insertionLoc;                    // The coerced insertionRec.
  1121.     DescType        theType;
  1122.     
  1123.                 //    Create the Apple Event.
  1124.     FailIfErr(AECreateAppleEvent(kAECoreSuite, kAECreateElement, &gSelfAddress, kAutoGenerateReturnID,
  1125.                                     kAnyTransactionID, &myAppleEvent));
  1126.                 //    Attach the class of the new element, which in this case is cWindow.
  1127.     theType = cWindow;
  1128.       FailIfErr(AEPutParamPtr(&myAppleEvent, keyAEObjectClass, typeType, (Ptr)&theType, sizeof(DescType)));
  1129.  
  1130.                 //    Create insertion loc, object is null container and position is beginning.
  1131.     FailIfErr(AECreateList(nil, 0, true, &insertionRec));            // Create an AE Record.
  1132.     theType = kAEBeginning;
  1133.     FailIfErr(AEPutKeyDesc(&insertionRec, keyAEObject, &gNullDesc));
  1134.     FailIfErr(AEPutKeyPtr(&insertionRec, keyAEPosition, typeEnumeration, (Ptr)&theType, sizeof(DescType)));
  1135.     FailIfErr(AECoerceDesc(&insertionRec, typeInsertionLoc, &insertionLoc));
  1136.                 // Now add the insertion location descriptor record to the Apple Event.
  1137.     FailIfErr(AEPutParamDesc(&myAppleEvent, keyAEInsertHere, &insertionLoc));
  1138.                 //    Send the Apple Event.
  1139.       FailIfErr(AESend(&myAppleEvent, &reply, kAENoReply+kAECanInteract, kAENormalPriority,
  1140.                                 kAEDefaultTimeout, nil, nil));
  1141.                 //    Now dispose of the AppleEvent and other records.
  1142.       MyDisposeDescs(&myAppleEvent, &insertionRec, &insertionLoc, kEndOfList);
  1143. }
  1144.  
  1145. //----------------------------------------------------------------------------------//
  1146. //    Respond to the Create Element Apple event and create a new window. For this        //
  1147. //    application, the keyAEInsertHere parameter is optional. If this parameter is     //
  1148. //    not present, a new window is created in the frontmost position.                    //
  1149. //    This routine also handles the optional initial data parameters (keyAEData and    //
  1150. //    keyAEPropData) if they are present. A window object specifier must be in the    //
  1151. //    keyAEData parameter, which is essentially used to make a clone. If the            //
  1152. //    property data exists, these properties will override those previously set.        //
  1153. //----------------------------------------------------------------------------------//
  1154. #pragma segment Main
  1155. pascal
  1156. OSErr HandleCreateElement(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  1157. {
  1158.     #pragma unused (refCon)
  1159.     AEDesc            windowObject, dataObject, propData, propObject, replyObject;
  1160.     AEDesc            insLocParam;
  1161.     AERecord        insLocRec;
  1162.     AERecord        dataPropParam;                    // Initial data parameters.
  1163.     AEKeyword        keyWord;                        // Property id code for PropData.
  1164.     DescType        theType, theClass, position;
  1165.     WindowPtr        window, relativeWindow, dataWindow, rplcWindow;
  1166.     Rect            bounds;
  1167.     Size            theSize;
  1168.     Str255            buffer;
  1169.     long            numItems;
  1170.     short            i;
  1171.     Boolean            isVisible;
  1172.     OSErr            err;
  1173.     
  1174.     if (err = AEGetParamPtr(theAppleEvent, keyAEObjectClass, typeType, &theType, (Ptr)&theClass,
  1175.                     sizeof(DescType), &theSize))
  1176.         return(err);
  1177.     if (theClass != cWindow)            // We only handle elements of the class cWindow.
  1178.         return(errAEEventNotHandled);
  1179.     position = typeNull;
  1180.     MyInitDescs(&windowObject,&dataObject,&propData,&propObject,&insLocParam,&dataPropParam,&replyObject,&insLocRec,kEndOfList);
  1181.             // Now get the insertion location record as an AERecord, if it exists.
  1182.     if (!(err = AEGetParamDesc(theAppleEvent, keyAEInsertHere, typeInsertionLoc, &insLocParam)))
  1183.     {        // coerce the insertion loc record to an AE record.
  1184.         err = AECoerceDesc(&insLocParam, typeAERecord, &insLocRec);
  1185.             //    Get the object as typeWildCard because it may be a null descriptor or an object.
  1186.         if (!(err = AEGetKeyDesc(&insLocRec, keyAEObject, typeWildCard, &windowObject)))
  1187.             if (!(err = AEGetKeyPtr(&insLocRec, keyAEPosition, typeEnumeration, &theType, (Ptr)&position,
  1188.                         sizeof(DescType), &theSize)))
  1189.             {
  1190.                 relativeWindow = nil;
  1191.                 err = FindRelativeWindow(&relativeWindow, &windowObject, position, &rplcWindow);
  1192.             }
  1193.     }
  1194.     else
  1195.         if (err == errAEDescNotFound)    // No insertion loc, make it frontmost by default.
  1196.         {
  1197.             relativeWindow = (WindowPtr)-1;
  1198.             position = kAEBeginning;
  1199.             err = noErr;        // Not an error for me because I make this param optional.
  1200.         }
  1201.  
  1202.     if (err)
  1203.         goto myExit;
  1204.         
  1205.                 // Check if optional data parameter is present.
  1206.     if (!(err = AEGetParamDesc(theAppleEvent,keyAEData,typeObjectSpecifier,&dataObject)))
  1207.     {
  1208.         if (dataWindow = ResolveToWindow(&dataObject))
  1209.         {
  1210.             window = CloneWindow(dataWindow, relativeWindow);
  1211.             isVisible = ((WindowPeek)dataWindow)->visible;
  1212.         }
  1213.         else
  1214.         {
  1215.             err = errAENoSuchObject;
  1216.             goto myExit;
  1217.         }
  1218.     }
  1219.     else
  1220.         if (err == errAEDescNotFound)    // The optional data parameter is not present.
  1221.         {
  1222.             if (window = CreateNewWindow(relativeWindow))
  1223.             {
  1224.             err = noErr;
  1225.             isVisible = true;
  1226.                 if (position == kAEReplace)            // Replace the window in the right position.
  1227.                 {
  1228.                     bounds = GetWindowBounds(rplcWindow);
  1229.                     MoveWindow(window, bounds.left, bounds.top, false);
  1230.                 }
  1231.             }
  1232.             else
  1233.             {
  1234.                 err = errAEEventNotHandled;        // couldn't create a new window.
  1235.                 goto myExit;
  1236.             }
  1237.         }
  1238.         else
  1239.             goto myExit;
  1240.  
  1241.     if (isVisible)                    // We set the visibility here because it may be changed
  1242.         ShowWindow(window);            // by the following property data.
  1243.  
  1244.             // Handle PropData parameter if it exists.        
  1245.     if (!(err = AEGetParamDesc(theAppleEvent,keyAEPropData,typeAERecord,&dataPropParam)))
  1246.     {
  1247.         AECountItems(&dataPropParam, &numItems);
  1248.         for (i = 1; i <= numItems; i++)
  1249.         {
  1250.             if (!(err = AEGetNthPtr(&dataPropParam,i,typeWildCard,&keyWord,&theType,&buffer,sizeof(Str255),&theSize)))
  1251.             {
  1252.                 AECreateDesc(keyWord, (Ptr)&window, sizeof(Ptr), &propObject);
  1253.                 AECreateDesc(theType, (Ptr)&buffer, theSize, &propData);
  1254.                 err = DoSetData(&propObject, &propData);
  1255.                 AEDisposeDesc(&propObject);
  1256.                 AEDisposeDesc(&propData);
  1257.                 if (err)
  1258.                     break;
  1259.             }
  1260.         }
  1261.     }
  1262.     
  1263.     if (!err || err == errAEDescNotFound)
  1264.     {
  1265.         if (position == kAEReplace)
  1266.             CloseTheWindow(rplcWindow);
  1267.         err = noErr;
  1268.         if (reply->dataHandle != nil)
  1269.         {
  1270.             CreateWindowObjectSpec(window, kIndexKeyForm, &replyObject);
  1271.             err = AEPutParamDesc(reply, keyAEResult, &replyObject);
  1272.         }
  1273.     }
  1274.         
  1275. myExit:
  1276.     MyDisposeDescs(&windowObject,&dataObject,&propData,&propObject,&insLocParam,&dataPropParam,&replyObject,&insLocRec,kEndOfList);
  1277.     return(err);
  1278. }
  1279.  
  1280. //----------------------------------------------------------------------------------//
  1281. //    Respond to the Do Objects Exist AE by attempting to resolve the object specifier//
  1282. //----------------------------------------------------------------------------------//
  1283. #pragma segment Main
  1284. pascal
  1285. OSErr HandleDoObjectsExist(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  1286. {
  1287.     #pragma unused (reply,refCon)
  1288.     AEDesc        target, token;
  1289.     Boolean        exists;
  1290.     OSErr        err;
  1291.     
  1292.     MyInitDescs(&target, &token, kEndOfList);
  1293.     if (!(err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeWildCard, &target)))
  1294.         if (!(err = GetMissingParams(theAppleEvent)))            // Check for missing params.
  1295.         {
  1296.             exists = true;
  1297.             token.descriptorType = typeNull;
  1298.             if (target.descriptorType != typeNull)
  1299.                 exists = (AEResolve(&target, kAEIDoMinimum, &token) == noErr);
  1300.  
  1301.                 //    Add data to the reply Apple event record.
  1302.               err = AEPutParamPtr(reply, keyDirectObject,typeBoolean,(Ptr)&exists,sizeof(Boolean));
  1303.         }
  1304. myExit:
  1305.     MyDisposeDescs(&target, &token, kEndOfList);
  1306.     return(err);
  1307. }
  1308.  
  1309. //----------------------------------------------------------------------------------//
  1310. //    Send the Set Data Apple Event with the object, property, and property data.        //
  1311. //    *NOTE*: I am sending myself the Set Data event in response to user interaction.    //
  1312. //    These actions have already occurred by this time, so I am sending the event        //
  1313. //    with the "don't execute" flag set for "smart" recorders.  A "smart" recorder    //
  1314. //    would check this flag when it intercepts the Apple event, and if it was set,    //
  1315. //    it wouldn't pass the event to the application.                                    //
  1316. //----------------------------------------------------------------------------------//
  1317. #pragma segment Main
  1318. void SendSetData( AEDesc*    propDesc,            // the property to set
  1319.                   AEDesc*    propData,            // the property data
  1320.                   AEDesc*    target  )        // object to set property of
  1321. {
  1322.     AppleEvent    myAppleEvent, reply;
  1323.     AEDesc        objectToSet;
  1324.  
  1325.     FailIfErr(AECreateAppleEvent(kAECoreSuite, kAESetData, &gSelfAddress, kAutoGenerateReturnID,
  1326.                                     kAnyTransactionID, &myAppleEvent));
  1327.                 //  Create the object specifier for the property of the object.
  1328.     FailIfErr(CreateObjSpecifier(cProperty, target, formPropertyID, propDesc, 
  1329.                                         false, &objectToSet));
  1330.                 //    Attach the property object specifier.
  1331.     FailIfErr(AEPutParamDesc(&myAppleEvent, keyDirectObject, &objectToSet));
  1332.                 //    Add the property data.
  1333.     FailIfErr(AEPutParamDesc(&myAppleEvent, keyAEData, propData));
  1334.       FailIfErr(AESend(&myAppleEvent, &reply, kAENoReply+kAECanInteract+kAEDontExecute, kAENormalPriority,
  1335.                                 kAEDefaultTimeout, nil, nil));
  1336.  
  1337.     AEDisposeDesc(&objectToSet);                    // Clean up.                                
  1338.     AEDisposeDesc(&myAppleEvent);
  1339. }
  1340.  
  1341. //----------------------------------------------------------------------------------//
  1342. //    To set the data of an object, the expected data is passed in its raw form with    //
  1343. //    the property type in the descriptorType field and the data in the dataHandle.    //
  1344. //----------------------------------------------------------------------------------//
  1345. #pragma segment Main
  1346. pascal
  1347. OSErr HandleSetData(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  1348. {
  1349.     #pragma unused (reply,refCon)
  1350.     AEDesc        target, data, token;
  1351.     OSErr        err;
  1352.     
  1353.     MyInitDescs(&target, &data,&token, kEndOfList);
  1354.         //    First, get the direct object. This is the object whose data is to be set.
  1355.     if (!(err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeObjectSpecifier, &target)))
  1356.         if (!(err = AEResolve(&target, kAEIDoMinimum, &token)))        // Resolve it.
  1357.            if (!(err = AEGetParamDesc(theAppleEvent, keyAEData, typeWildCard, &data)))
  1358.               err = DoSetData(&token, &data);
  1359.     MyDisposeDescs(&target, &data, &token, kEndOfList);
  1360.     return(err);
  1361. }
  1362.  
  1363. //----------------------------------------------------------------------------------//
  1364. //    Return a reply to the Get Data or Get Data Size Apple Event for the requested    //
  1365. //    data. The refcon parameter is used to distinguish the two events. If typeBest    //
  1366. //    is the requested return type, the data's descriptor type is the result type.    //
  1367. //    **NOTE: Do not use the same descriptor as source and dest in AECoerceDesc().    //
  1368. //    This routine creates a copy of the source, and then it is impossible to dispose    //
  1369. //    of the memory originally contained in the source's dataHandle.                    //
  1370. //    2/25/92 - Removed FailIfErr calls. Now the error is returned as a result.        //
  1371. //----------------------------------------------------------------------------------//
  1372. #pragma segment Main
  1373. pascal
  1374. OSErr HandleGetData( AppleEvent*    theAppleEvent,
  1375.                      AppleEvent*    reply,
  1376.                      long            refCon    )        // kAEGetData or kAEGetDataSize.
  1377. {
  1378.     AEDesc            theObject, token;                // direct object and resolved token.
  1379.     AEDesc            objectData, tempDesc;            // object data, and coerced data.
  1380.     DescType        reqType;
  1381.     WindowPtr        window;
  1382.     Size            theSize;
  1383.     OSErr            err;
  1384.     
  1385.     MyInitDescs(&theObject, &objectData, &token, kEndOfList);
  1386.             //    First, get the direct objet.
  1387.     if (err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeObjectSpecifier, &theObject))
  1388.         goto myExit;
  1389.             //    Next, get the requested return type, if it exists.
  1390.     if (err = AEGetParamPtr(theAppleEvent, keyAERequestedType, typeType, &reqType,
  1391.                                 (Ptr)&reqType, sizeof(DescType), &theSize))
  1392.     {
  1393.         if (err == errAEDescNotFound)        // not an error if return type is not found
  1394.         {
  1395.             err = noErr;
  1396.             reqType = typeWildCard;
  1397.         }
  1398.         else
  1399.             goto myExit;
  1400.     }
  1401.     if (err = GetMissingParams(theAppleEvent))            // check for missing params
  1402.         goto myExit;
  1403.  
  1404.             //    Resolve the object specifier and get the token containing the property and container.
  1405.     if (!(err = AEResolve(&theObject, kAEIDoMinimum, &token)))
  1406.         if (window = (WindowPtr)*(LongPtr)*token.dataHandle)        // Nil for application; WindowPtr for window
  1407.             err = GetWindowData(token.descriptorType, window, &objectData);
  1408.         else
  1409.             err = GetAppData(token.descriptorType, &objectData);
  1410.  
  1411.     if (err == noErr && reply->dataHandle != nil)
  1412.     {        //    Add data to the reply Apple event record.
  1413.         if (reqType != typeWildCard && reqType != typeBest &&
  1414.             reqType != objectData.descriptorType)
  1415.         {
  1416.             err = AECoerceDesc(&objectData, reqType, &tempDesc);
  1417.             MyDisposeDescs(&objectData, kEndOfList);
  1418.             objectData.descriptorType = tempDesc.descriptorType;
  1419.             objectData.dataHandle = tempDesc.dataHandle;
  1420.         }
  1421.         if (!err)
  1422.         {
  1423.             if (refCon == kAEGetData)                // return data
  1424.                 err = AEPutParamDesc(reply, keyAEResult, &objectData);
  1425.             else if (refCon == kAEGetDataSize)        // return data size
  1426.             {
  1427.                 theSize = GetHandleSize(objectData.dataHandle);
  1428.                   err = AEPutParamPtr(reply, keyAEResult, typeLongInteger, (Ptr)&theSize, sizeof(long));
  1429.             }
  1430.         }
  1431.     }
  1432.     
  1433. myExit:
  1434.     MyDisposeDescs(&theObject, &objectData, &token, kEndOfList);
  1435.     return(err);
  1436. }
  1437.  
  1438. //----------------------------------------------------------------------------------//
  1439. //    Send a Move Apple event to myself in response to a user selecting a window        //
  1440. //    and making it frontmost. This event is sent with the insertion location record    //
  1441. //    specifying the beginning of the null container. If the index is non-zero, this    //
  1442. //    indicates that the move event has already been performed by DragWindow(). Thus,    //
  1443. //    this event is passed with the don't execute flag set.                            //
  1444. //----------------------------------------------------------------------------------//
  1445. #pragma segment Main
  1446. void SendMoveEvent(WindowPtr windowToMove, long index)
  1447. {
  1448.     AppleEvent        myAppleEvent, reply, windowObject;
  1449.     AERecord        insertionRec;                    // Insertion Loc record.
  1450.     AEDesc            insertionLoc;                    // The coerced insertionRec.
  1451.     DescType        theType;
  1452.     
  1453.         //    Create the Apple Event.
  1454.     FailIfErr(AECreateAppleEvent(kAECoreSuite, kAEMove, &gSelfAddress, kAutoGenerateReturnID,
  1455.                                     kAnyTransactionID, &myAppleEvent));
  1456.         //    Create the object spec for the window to move.
  1457.     FailIfErr(CreateWindowObjectSpec(windowToMove, kIndexKeyForm, &windowObject));
  1458.     FailIfErr(AEPutParamDesc(&myAppleEvent, keyDirectObject, &windowObject));
  1459.  
  1460.         //    Create insertion loc record for beginning of null container.
  1461.     FailIfErr(AECreateList(nil, 0, true, &insertionRec));            // Create an AE Record.
  1462.     theType = kAEBeginning;
  1463.     FailIfErr(AEPutKeyDesc(&insertionRec, keyAEObject, &gNullDesc));
  1464.     FailIfErr(AEPutKeyPtr(&insertionRec,keyAEPosition,typeEnumeration,(Ptr)&theType,sizeof(DescType)));
  1465.     FailIfErr(AECoerceDesc(&insertionRec, typeInsertionLoc, &insertionLoc));
  1466.         // Now add the insertion location descriptor record to the Apple Event.
  1467.     FailIfErr(AEPutParamDesc(&myAppleEvent, keyAEInsertHere, &insertionLoc));
  1468.         //    Send the Apple Event.
  1469.     if (index)
  1470.           FailIfErr(AESend(&myAppleEvent, &reply, kAENoReply+kAECanInteract+kAEDontExecute,
  1471.                             kAENormalPriority, kAEDefaultTimeout, nil, nil));
  1472.     else
  1473.           FailIfErr(AESend(&myAppleEvent, &reply, kAENoReply+kAECanInteract,
  1474.                             kAENormalPriority, kAEDefaultTimeout, nil, nil));
  1475.  
  1476.         //    Now dispose of the AppleEvent and other records.
  1477.     MyDisposeDescs(&myAppleEvent,&windowObject,&insertionRec,&insertionLoc,kEndOfList);
  1478. }
  1479.  
  1480. //----------------------------------------------------------------------------------//
  1481. //    Respond to the Move Apple Event by reordering the window list.  For CoreSample,    //
  1482. //    the keyAEInsertHere parameter is optional. If this parameter does not exist,    //
  1483. //    the specified window will move the  to the front.                                //
  1484. //----------------------------------------------------------------------------------//
  1485. #pragma segment Main
  1486. pascal
  1487. OSErr HandleMove(AppleEvent* theAppleEvent, AppleEvent* reply, long refCon)
  1488. {
  1489.     #pragma unused (refCon)
  1490.     AEDesc            object, windowObj, replyObj, insertionLoc;
  1491.     AERecord        insertionRec;
  1492.     DescType        theType, position;
  1493.     WindowPtr        windowToMove, relativeWindow, rplcWindow;
  1494.     Rect            bounds;
  1495.     Size            paramSize;
  1496.     OSErr            err;
  1497.     
  1498.     MyInitDescs(&object,&windowObj,&insertionLoc,&insertionRec,&replyObj,kEndOfList);
  1499.         //    First, get the direct parameter, the object to move.
  1500.     if (err = AEGetParamDesc(theAppleEvent, keyDirectObject, typeObjectSpecifier, &object))
  1501.         goto myExit;
  1502.     if (!(windowToMove = ResolveToWindow(&object)))            // Check if valid window object.
  1503.     {
  1504.         err = errAENoSuchObject;
  1505.         goto myExit;
  1506.     }
  1507.  
  1508.         // Retrieve the insertion location record, if it exists.
  1509.     if ((err = AEGetParamDesc(theAppleEvent,keyAEInsertHere,typeInsertionLoc,&insertionLoc)) == errAEDescNotFound)
  1510.     {            // Execute *MY* default behavior since insertion loc param not present.
  1511.         SelectWindow(windowToMove);
  1512.         err = noErr;
  1513.         goto myExit;
  1514.     }
  1515.     else
  1516.         if (err)
  1517.             goto myExit;
  1518.         else            // get data from insertion loc and coerce it to typeAERecord.
  1519.         {
  1520.             if ((err = GetMissingParams(theAppleEvent))  ||
  1521.                 (err = AECoerceDesc(&insertionLoc, typeAERecord, &insertionRec)) || 
  1522.                 (err = AEGetKeyDesc(&insertionRec,keyAEObject,typeWildCard,&windowObj)) ||
  1523.                 (err = AEGetKeyPtr(&insertionRec,keyAEPosition,typeEnumeration,&theType,
  1524.                                     (Ptr)&position,sizeof(DescType),¶mSize)))
  1525.                     goto myExit;
  1526.         }
  1527.  
  1528.     if (!(err = FindRelativeWindow(&relativeWindow,&windowObj,position,&rplcWindow)))
  1529.     {
  1530.         if (position == kAEReplace)
  1531.             if (windowToMove == rplcWindow)
  1532.                 goto myExit;                // do nothing.
  1533.             else
  1534.             {
  1535.                 bounds = GetWindowBounds(rplcWindow);
  1536.                 CloseTheWindow(rplcWindow);
  1537.                 MoveWindow(windowToMove, bounds.left, bounds.top, false);
  1538.             }
  1539.  
  1540.         if (relativeWindow == (WindowPtr)-1)        // [pwpc]
  1541.             SelectWindow(windowToMove);
  1542.         else
  1543.             if (windowToMove != relativeWindow)
  1544.                 SendBehind(windowToMove, relativeWindow);        // NOTE: may have to call PaintOne and
  1545.                                                                 // CalcVis if after; see IM I-286
  1546.         if (position == kAEReplace && windowToMove != rplcWindow)
  1547.         {
  1548.             bounds = GetWindowBounds(rplcWindow);
  1549.             CloseTheWindow(rplcWindow);
  1550.             MoveWindow(windowToMove, bounds.left, bounds.top, false);
  1551.         }
  1552.     }
  1553.  
  1554. myExit:
  1555.     if (!err)
  1556.         if (reply->dataHandle != nil)
  1557.         {
  1558.             CreateWindowObjectSpec(windowToMove, kIndexKeyForm, &replyObj);
  1559.             err = AEPutParamDesc(reply, keyAEResult, &replyObj);
  1560.         }
  1561.     MyDisposeDescs(&object,&windowObj,&insertionLoc,&insertionRec,&replyObj,kEndOfList);
  1562.     return(err);
  1563. }
  1564.  
  1565. //----------------------------------------------------------------------------------//
  1566. //    Set up the descriptor records needed to set the data for the bounds, position,    //
  1567. //    and zoomed properties.  The bounds is set in response to sizing a window; the    //
  1568. //    position is set after dragging a window; and the isZoomed property is set when    //
  1569. //    zooming a window in or out.                                                        //
  1570. //----------------------------------------------------------------------------------//
  1571. #pragma segment Main
  1572. void SetUpPropertyData( WindowPtr        window,            // Window object.
  1573.                         DescType        propType,        // Property descriptor type.
  1574.                         DescType        dataType,        // Descriptor type for data.
  1575.                         Size            dataSize   )    // Size of data.
  1576. {
  1577.     AEDesc        windowObject, theData, theProperty;
  1578.     Rect        bounds;
  1579.     Boolean        isZoomed;
  1580.     
  1581.     MyInitDescs(&windowObject, &theData, &theProperty, kEndOfList);
  1582.     if (propType == pIsZoomed)
  1583.     {
  1584.         isZoomed = (Boolean)GetWRefCon(window);
  1585.         FailIfErr(AECreateDesc(dataType,(Ptr)&isZoomed,dataSize,&theData));
  1586.     }
  1587.     else        // it's either pBounds or pPosition.
  1588.     {
  1589.           bounds = GetWindowBounds(window);
  1590.         FailIfErr(AECreateDesc(dataType, (Ptr)&bounds, dataSize, &theData));
  1591.     }
  1592.         
  1593.     CreateWindowObjectSpec(window, kIndexKeyForm, &windowObject);
  1594.     FailIfErr(AECreateDesc(typeType, (Ptr)&propType, sizeof(DescType), &theProperty));
  1595.  
  1596.     SendSetData(&theProperty, &theData, &windowObject);
  1597.     MyDisposeDescs(&windowObject, &theData, &theProperty, kEndOfList);
  1598. }
  1599.  
  1600. //----------------------------------------------------------------------------------//
  1601. //    Set the property data for the specified object.  For now, we only handle window    //
  1602. //    objects, and you may only set the modifiable properties (defined in Registry).    //
  1603. //    *NOTE*:  We do not allow the application's properties to be modified.            //
  1604. //----------------------------------------------------------------------------------//
  1605. #pragma segment Main
  1606. OSErr DoSetData( AEDesc*    token,                // Contains the property and object.
  1607.                  AEDesc*    data    )            // Contains the data to set.
  1608. {
  1609.     AEDesc            propData;            // Property data.
  1610.     Rect            bounds;
  1611.     GrafPtr            oldPort;
  1612.     WindowPtr        window, behindWindow;
  1613.     Str255            name;
  1614.     long            newIndex;
  1615.     short            part;
  1616.     Boolean            value;
  1617.     Point            pt;
  1618.     OSErr            err;
  1619.  
  1620.     err = noErr;
  1621.     if (window = (WindowPtr)*(LongPtr)*(token->dataHandle))
  1622.     {
  1623.         GetPort(&oldPort);
  1624.         switch (token->descriptorType)
  1625.         {
  1626.             case pBounds:
  1627.                 if (data->descriptorType != typeQDRectangle)
  1628.                 {
  1629.                     propData.dataHandle = nil;
  1630.                     err = AECoerceDesc(data, typeQDRectangle, &propData);
  1631.                     bounds = *(Rect *)*propData.dataHandle;        // Get content region.
  1632.                     MyDisposeDescs(&propData, kEndOfList);
  1633.                 }
  1634.                 else
  1635.                     bounds = *(Rect *)*data->dataHandle;        // Get content region.
  1636.         
  1637.                 if (!err)
  1638.                 {
  1639.                     SetPort(window);
  1640.                     InvalRect(&window->portRect);
  1641.         
  1642.                         // Real applications may want to make a sanity check on the new bounds.        
  1643.                     MoveWindow(window, bounds.left, bounds.top, false);
  1644.                      SizeWindow(window, bounds.right-bounds.left, bounds.bottom-bounds.top, true);
  1645.                     InvalRect(&window->portRect);
  1646.                 }
  1647.                 break;
  1648.             
  1649.             case pIndex:
  1650.                 if (DescToLong(data,&newIndex) != noErr)
  1651.                     return(errAECoercionFail);        // Data cannot be coerced.
  1652.  
  1653.                 if (newIndex > gNumWindowsOpen)
  1654.                     err = errAEIndexTooLarge;
  1655.                 else
  1656.                 {
  1657.                     if (newIndex == 1)
  1658.                         SelectWindow(window);
  1659.                     else
  1660.                         if (behindWindow = GetWindowAtIndex(newIndex))
  1661.                             SendBehind(window, behindWindow);
  1662.                         else
  1663.                             err = errAEEventFailed;
  1664.                 }
  1665.                 break;
  1666.                 
  1667.             case pIsZoomed:
  1668.                 if (DescToBoolean(data,&value) != noErr)
  1669.                     return(errAECoercionFail);            // Data cannot be coerced.
  1670.                     
  1671.                 part = value ? inZoomOut : inZoomIn;
  1672.                 ZoomIt(window, part);
  1673.                 break;
  1674.  
  1675.             case pName:
  1676.                 if (DescToPString(data,name,kMaxStrSize) != noErr)
  1677.                     return(errAECoercionFail);
  1678.                 SetWTitle(window, name);
  1679.                 break;
  1680.             
  1681.             case pPosition:
  1682.                 if (data->descriptorType != typeQDPoint)
  1683.                 {
  1684.                     propData.dataHandle = nil;
  1685.                     err = AECoerceDesc(data, typeQDPoint, &propData);
  1686.                     pt = *(Point *)*propData.dataHandle;
  1687.                     MyDisposeDescs(&propData, kEndOfList);
  1688.                 }
  1689.                 else
  1690.                     pt = *(Point *)*data->dataHandle;
  1691.  
  1692.                 if (!err)
  1693.                 {
  1694.                         // Real applications may want to make a sanity check on the new loc.
  1695.                     SetPort(window);
  1696.                     MoveWindow(window, pt.h, pt.v, false);
  1697.                     InvalRect(&window->portRect);
  1698.                 }
  1699.                 break;
  1700.             
  1701.             case pVisible:
  1702.                 if (DescToBoolean(data,&value) != noErr)
  1703.                     return(errAECoercionFail);        // Data cannot be coerced.
  1704.                 if (value)
  1705.                     ShowWindow(window);
  1706.                 else
  1707.                     HideWindow(window);
  1708.                 break;
  1709.                 
  1710.             default:                        // No other properties are modifiable.
  1711.                 return(errAENotModifiable);
  1712.         }
  1713.         SetPort(oldPort);
  1714.     }
  1715.     else
  1716.         return(errAEEventFailed);
  1717.     return(err);
  1718. }
  1719.  
  1720. //----------------------------------------------------------------------------------//
  1721. //    This is a dummy handler that receives Apple events which I don't handle.  It     //
  1722. //    is mainly provided as a stub in order to support all the events in the             //
  1723. //    required suite, as well as the entire core suite.  This is the handler for the    //
  1724. //    Open Document and Print Document events (required suite); and the Save, Get     //
  1725. //    Class Info,    and Get Event Info events (core suite).  The Get Class Info and Get    //
  1726. //    Event Info events "MAY" be supported internally in the future, so applications    //
  1727. //    will not need to handle these events themselves.  This support may be provided    //
  1728. //    since it would be consistent across all applications, and the information may    //
  1729. //    be retrieved from the 'aeut'/'aete' resources.                                    //
  1730. //----------------------------------------------------------------------------------//
  1731. #pragma segment Main
  1732. pascal
  1733. OSErr DummyHandler( AppleEvent        *theAppleEvent,
  1734.                     AppleEvent        *reply,
  1735.                     long            refCon    )
  1736. {
  1737.     #pragma unused (theAppleEvent,reply,refCon)
  1738.     return(errAEEventNotHandled);
  1739. }
  1740.  
  1741. //----------------------------------------------------------------------------------//
  1742. //    Locate the window that is relative to the specified window object at the        //
  1743. //    insertion position.  If the location is replace, the window to replace is         //
  1744. //    closed, and its bounds are returned to the calling routine.                        //
  1745. //    **Note**: if windowObj is used within this routine, the object param will        //
  1746. //    contain the same dataHandle. This will be disposed of by the calling routine.    //
  1747. //----------------------------------------------------------------------------------//
  1748. #pragma segment Main
  1749. OSErr FindRelativeWindow( WindowPtr*    relativeWindow,    // window before insertion loc.
  1750.                           AEDesc*        object,            // object to be relative to.
  1751.                           DescType        position,            // insertion position.
  1752.                           WindowPtr*    replaceWindow )    // window to replace.
  1753. {
  1754.     AEDesc        windowObj;                    // Coerced descriptor.
  1755.     WindowPtr    windowToReplace;
  1756.     long        index;
  1757.     OSErr        err;
  1758.     
  1759.     err = noErr;
  1760.     *replaceWindow = nil;
  1761.     switch(position)
  1762.     {
  1763.         case kAEBeginning:                        // The object should be the container.
  1764.             if (object->descriptorType == typeNull)
  1765.                 *relativeWindow = (WindowPtr)-1;
  1766.             else
  1767.                 err = errAENoSuchObject;
  1768.             break;
  1769.         
  1770.         case kAEEnd:                            // The object should be the container.
  1771.             if (object->descriptorType == typeNull)
  1772.                 *relativeWindow = nil;
  1773.             else
  1774.                 err = errAENoSuchObject;
  1775.             break;
  1776.             
  1777.         case kAEBefore:                            // The object should be an object specifier.
  1778.         case kAEReplace:
  1779.             if (object->descriptorType != typeObjectSpecifier)
  1780.             {
  1781.                 err = AECoerceDesc(object, typeObjectSpecifier, &windowObj);
  1782.                 MyDisposeDescs(object, kEndOfList);
  1783.                 object->descriptorType = windowObj.descriptorType;
  1784.                 object->dataHandle = windowObj.dataHandle;
  1785.             }
  1786.             
  1787.             if (!err)
  1788.                 if (windowToReplace = ResolveToWindow(object))
  1789.                 {
  1790.                     index = GetWindowIndexNum(windowToReplace);
  1791.                     *relativeWindow = (index==1) ? (WindowPtr)-1 : GetWindowAtIndex(index-1);
  1792.                     if (position == kAEReplace)
  1793.                         *replaceWindow = windowToReplace;
  1794.             }
  1795.             else            // We weren't able to resolve the object specifier to a window.
  1796.                 err = errAENoSuchObject;
  1797.             break;
  1798.             
  1799.         case kAEAfter:                        // The object should be an object specifier.
  1800.             if (object->descriptorType != typeObjectSpecifier)
  1801.             {
  1802.                 err = AECoerceDesc(object,typeObjectSpecifier,&windowObj);
  1803.                 MyDisposeDescs(object, kEndOfList);
  1804.                 object->descriptorType = windowObj.descriptorType;
  1805.                 object->dataHandle = windowObj.dataHandle;
  1806.             }
  1807.  
  1808.             if (!err)
  1809.                 if (!(*relativeWindow = ResolveToWindow(object)))
  1810.                     err = errAENoSuchObject;
  1811.             break;
  1812.             
  1813.         default:
  1814.             return(errAEEventNotHandled);
  1815.     }
  1816.     return(err);
  1817. }
  1818.  
  1819. //----------------------------------------------------------------------------------//
  1820. //    Retrieves the data for the specified property of the window.  The result token    //
  1821. //    contains the type of the data in the descriptorType field, and the data itself    //
  1822. //    in the dataHandle field.  I know my application's window properties             //
  1823. //    (i.e., has title bar, has close box, is zoomable, etc.), so I set up the         //
  1824. //    result token accordingly.  If your application handles various window types,    //
  1825. //    you may need to look at the window defproc to determine which type of window it    //
  1826. //    is.  If the property is pBestType or pDefaultType, I return an object specifier//
  1827. //    for the window which may be used to easily reference it.                        //
  1828. //----------------------------------------------------------------------------------//
  1829. #pragma segment Main
  1830. OSErr GetWindowData( DescType        theProperty,        // Window property.
  1831.                      WindowPtr        window,
  1832.                      AEDesc            *result    )            // Contains the result upon return.
  1833. {
  1834.     DescType        theType;
  1835.     Str255            title;
  1836.     Rect            bounds;
  1837.     long            index;
  1838.     Boolean            myAnswer;
  1839.  
  1840.     switch (theProperty)
  1841.     {
  1842.         case pBestType:
  1843.         case pDefaultType:
  1844.             return(CreateWindowObjectSpec(window, kIndexKeyForm, result));
  1845.  
  1846.         case pBounds:
  1847.               bounds = GetWindowBounds(window);
  1848.             return(AECreateDesc(typeQDRectangle, (Ptr)&bounds, sizeof(Rect), result));
  1849.             
  1850.         case pClass:
  1851.             theType = cWindow;
  1852.             return(AECreateDesc(typeType, (Ptr)&theType, sizeof(DescType), result));
  1853.  
  1854.         case pIndex:
  1855.             index = GetWindowIndexNum(window);
  1856.             return(AECreateDesc(typeLongInteger, (Ptr)&index, sizeof(long), result));
  1857.                 
  1858.         case pName:
  1859.             GetWTitle(window, title);
  1860.             return(AECreateDesc(typeChar, (Ptr)&title[1], title[0], result));
  1861.  
  1862.         case pPosition:
  1863.               bounds = GetWindowBounds(window);
  1864.             return(AECreateDesc(typeQDPoint, (Ptr)&bounds, sizeof(Point), result));
  1865.  
  1866.         case pHasCloseBox:
  1867.         case pHasTitleBar:
  1868.         case pIsResizable:
  1869.         case pIsZoomable:
  1870.             myAnswer = true;
  1871.             return(AECreateDesc(typeBoolean, (Ptr)&myAnswer, sizeof(Boolean), result));
  1872.  
  1873.         case pIsFloating:
  1874.         case pIsModal:
  1875.             myAnswer = false;
  1876.             return(AECreateDesc(typeBoolean, (Ptr)&myAnswer, sizeof(Boolean), result));
  1877.             
  1878.         case pIsZoomed:
  1879.             myAnswer = GetWRefCon(window);
  1880.             return(AECreateDesc(typeBoolean, (Ptr)&myAnswer, sizeof(Boolean), result));
  1881.         
  1882.         case pVisible:                    // Must check this because it is modifiable.
  1883.             myAnswer = ((WindowPeek)window)->visible;
  1884.             return(AECreateDesc(typeBoolean, (Ptr)&myAnswer, sizeof(Boolean), result));
  1885.  
  1886.         case pSelection:                // No selection in CoreSample.
  1887.             return(errAENoSuchObject);
  1888.  
  1889.         default:                        // We don't handle requested property.
  1890.             return(errAEEventNotHandled);
  1891.     }
  1892. }
  1893.  
  1894. //----------------------------------------------------------------------------------//
  1895. //    Get the property data for the application and return it in the result parameter.//
  1896. //    The result token contains the property type in the descriptorType field, and    //
  1897. //    a nil value in the dataHandle field to represent the null application.            //
  1898. //----------------------------------------------------------------------------------//
  1899. #pragma segment Main
  1900. OSErr GetAppData(    DescType    theProperty,
  1901.                     AEDesc*        result    )        // Descriptor record to hold the property data.
  1902. {
  1903.     ProcessInfoRec            myProcessInfo;        // [pwpc]
  1904.     DescType                theType;
  1905.     short                    refNum;
  1906.     Str255                    name;
  1907.     Handle                    myHandle;
  1908.     ProcessSerialNumber        thePSN, currentProcess;
  1909.     Boolean                    isFront;
  1910.     OSErr                    err;
  1911.  
  1912.     switch (theProperty)
  1913.     {
  1914.         case pBestType:                    // Return the null descriptor representing
  1915.         case pDefaultType:                // the application.
  1916.             return(AEDuplicateDesc(&gNullDesc, result));
  1917.  
  1918.         case pClass:
  1919.             theType = cApplication;
  1920.             return(AECreateDesc(typeType,(Ptr)&theType,sizeof(DescType),result));
  1921.             
  1922.         case pName:
  1923.             // [pwpc] Clear out the name, and then call the process manager to get
  1924.             // the string for the name of our application.
  1925.             
  1926.             name[0] = 0;
  1927.             myProcessInfo.processInfoLength = sizeof(myProcessInfo); 
  1928.             myProcessInfo.processName = name;
  1929.             myProcessInfo.processAppSpec = NULL;
  1930.             
  1931.             GetCurrentProcess(¤tProcess);
  1932.             GetProcessInformation(¤tProcess, &myProcessInfo);
  1933.         
  1934.             // Create an AEDesc returning the application name string
  1935.             // returned by the process manager.
  1936.  
  1937.             return(AECreateDesc(typeChar, (Ptr)&name[1], name[0], result));
  1938.  
  1939.         case pIsFrontProcess:
  1940.             GetFrontProcess(&thePSN);
  1941.             SameProcess(&gSelfPSN, &thePSN, &isFront);
  1942.             return(AECreateDesc(typeBoolean,(Ptr)&isFront,sizeof(Boolean),result));
  1943.             
  1944.         case pVersion:
  1945.             refNum = CurResFile();            // save current resource
  1946.             UseResFile(gRefNum);            // set this resource to be current
  1947.             myHandle = (Handle)Get1Resource((ResType)'vers', 1);
  1948.               HLock(myHandle);
  1949.              err = AECreateDesc(typeVersion, *myHandle, GetHandleSize(myHandle), result);
  1950.               HUnlock(myHandle);
  1951.             UseResFile(refNum);                // reset back to resource previously set
  1952.             return(err);
  1953.  
  1954.         default:                // We don't handle the requested property.
  1955.             return(errAEEventNotHandled);
  1956.     }
  1957. }
  1958.  
  1959. //----------------------------------------------------------------------------------//
  1960. //    Create an object specifier for the window with the indicated key form.            //
  1961. //----------------------------------------------------------------------------------//
  1962. #pragma segment Main
  1963. OSErr CreateWindowObjectSpec( WindowPtr    window,
  1964.                               short        keyForm,        // index or name key form.
  1965.                                 AEDesc*    objectSpec )    // Resulting object specifier.
  1966. {
  1967.     AEDesc        data;
  1968.     Str255        title;
  1969.     long        index;
  1970.     OSErr        err;
  1971.  
  1972.     MyInitDescs(&data, kEndOfList);
  1973.     switch(keyForm)
  1974.     {
  1975.         case kNameKeyForm:                    // Object specifier with name.
  1976.             GetWTitle(window, title);
  1977.             if (!(err = AECreateDesc(typeChar, (Ptr)&title[1], title[0], &data)))                
  1978.                 err = CreateObjSpecifier(cWindow, &gNullDesc, formName, &data,
  1979.                                     false, objectSpec);
  1980.             break;
  1981.             
  1982.         case kIndexKeyForm:                    // Object specifier with index.
  1983.             index = GetWindowIndexNum(window);
  1984.             if (!(err = CreateOffsetDescriptor(index, &data)))
  1985.                 err = CreateObjSpecifier(cWindow, &gNullDesc, formAbsolutePosition, &data,
  1986.                                     false, objectSpec);
  1987.             break;
  1988.     }
  1989.     MyDisposeDescs(&data, kEndOfList);
  1990.     return(err);
  1991. }
  1992.  
  1993. //----------------------------------------------------------------------------------//
  1994. //    Check to see if there exists any additional parameters in the Apple Event.      //
  1995. //    If so, return an error to the calling routine.                                    //
  1996. //----------------------------------------------------------------------------------//
  1997. #pragma segment Main
  1998. OSErr GetMissingParams(AppleEvent*  theAppleEvent)
  1999. {
  2000.     DescType    theType;
  2001.     Size        actualSize;
  2002.     OSErr        err;
  2003.     
  2004.     err = AEGetAttributePtr(theAppleEvent, keyMissedKeywordAttr, typeWildCard,
  2005.                                 &theType, nil, 0, &actualSize);
  2006.     if (err == errAEDescNotFound)
  2007.         return(noErr);
  2008.     else
  2009.         return(errAEEventNotHandled);
  2010. }
  2011.  
  2012. //----------------------------------------------------------------------------------//
  2013. //    If a reply is expected, the error number is returned in the reply parameter.    //
  2014. //----------------------------------------------------------------------------------//
  2015. #pragma segment Main
  2016. void ReportError( AppleEvent*    reply,
  2017.                   long            err    )
  2018. {
  2019.     if (reply->dataHandle != nil && err != noErr)
  2020.         FailIfErr(AEPutParamPtr(reply,keyErrorNumber,typeLongInteger,(Ptr)&err,sizeof(long)));
  2021. }
  2022.  
  2023. //----------------------------------------------------------------------------------//
  2024. //    This routine returns the window object contained in the given object specifier.    //
  2025. //    If the resolution does not return a descriptor record of type cWindow, nil is     //
  2026. //    returned as a result.                                                            //
  2027. //----------------------------------------------------------------------------------//
  2028. #pragma segment Main
  2029. WindowPtr ResolveToWindow(AEDesc*  objectSpecifier)
  2030. {
  2031.     AEDesc        token;
  2032.     WindowPtr    window;
  2033.  
  2034.  
  2035.     MyInitDescs(&token, kEndOfList);
  2036.     window = nil;
  2037.     if (objectSpecifier->descriptorType == typeObjectSpecifier)
  2038.         if (!(AEResolve(objectSpecifier, kAEIDoMinimum, &token)))
  2039.             if (token.descriptorType == cWindow)
  2040.                 window = (WindowPtr)*((LongPtr)*(token.dataHandle));
  2041.  
  2042.     MyDisposeDescs(&token, kEndOfList);
  2043.     return(window);
  2044. }
  2045.  
  2046. //----------------------------------------------------------------------------------//
  2047. //    Retrieve the window from the null container by the key form and return its        //
  2048. //    pointer in the dataHandle field of resultToken.                                    //
  2049. //----------------------------------------------------------------------------------//
  2050. #pragma segment Main
  2051. pascal
  2052. OSErr WindowAccessor( DescType        classWanted,        // window class
  2053.                       AEDesc*        container,            // the application (null container)
  2054.                       DescType        containerClass, 
  2055.                       DescType        keyform,
  2056.                       AEDesc*        selectionData,
  2057.                       AEDesc*        resultToken,        // specified window is returned in result
  2058.                       long             theRefCon     )
  2059. {
  2060.     #pragma unused (classWanted,container,containerClass,theRefCon)
  2061.     WindowPtr        window;
  2062.     DescType        seldataType;
  2063.     Str255            title;
  2064.     long            index;
  2065.     OSErr            err;
  2066.  
  2067.     window = nil;
  2068.     err = noErr;    
  2069.     if (!gNumWindowsOpen)
  2070.         return(errAENoSuchObject);
  2071.     else
  2072.     {
  2073.         seldataType = selectionData->descriptorType;
  2074.     
  2075.         switch(keyform)
  2076.         {
  2077.             case formName:                                    // Window title.
  2078.                 if (DescToPString(selectionData,title,kMaxStrSize) != noErr)
  2079.                     return(errAECoercionFail);
  2080.                 if (!(window = GetWindowWithTitle(title)))
  2081.                     return(errAENoSuchObject);        // Window was not found.
  2082.                 break;
  2083.             
  2084.             case formAbsolutePosition:
  2085.                 if (DescToLong(selectionData,&index) != noErr)
  2086.                     return(errAECoercionFail);        // Data cannot be coerced.
  2087.                 if (!(window = GetWindowAtIndex(index)))
  2088.                     return(errAENoSuchObject);            // Window was not found.
  2089.                 break;    
  2090.             
  2091.             default:                                    // I don't handle any other key forms.
  2092.                 return(errAEEventNotHandled);
  2093.         }
  2094.     }
  2095.     return(AECreateDesc(cWindow, (Ptr)&window, sizeof(Ptr), resultToken));
  2096. }
  2097.  
  2098. //----------------------------------------------------------------------------------//
  2099. //    Return a token representing the property for the containing window.  The token    //
  2100. //    is returned with the property and window pointer.                                //
  2101. //----------------------------------------------------------------------------------//
  2102. #pragma segment Main
  2103. pascal
  2104. OSErr WindowPropertyAccessor( DescType        classWanted,        // Property class
  2105.                                 AEDesc*        container,            // Window object
  2106.                               DescType        containerClass, 
  2107.                               DescType        form,
  2108.                               AEDesc*        selectionData,
  2109.                               AEDesc*        resultToken,
  2110.                               long             theRefCon     )
  2111. {
  2112.     #pragma unused (containerClass, theRefCon)
  2113.     Ptr                window;
  2114.     DescType        propType;
  2115.     
  2116.             //    Let's make sure we're accessing a valid descriptor type.
  2117.     if ((classWanted != cProperty) || (form != formPropertyID))
  2118.         return(errAEWrongDataType);
  2119.  
  2120.     window = (Ptr)*(LongPtr)*(container->dataHandle);        // Get the window pointer.
  2121.     propType = *(LongPtr)*selectionData->dataHandle;        // Get the property type.
  2122.     return(AECreateDesc(propType, (Ptr)&window, sizeof(Ptr), resultToken)); 
  2123. }
  2124.  
  2125. //----------------------------------------------------------------------------------//
  2126. //    Return a token that contains the property type and nil to represent the null    //
  2127. //    container (the application).                                                    //
  2128. //----------------------------------------------------------------------------------//
  2129. #pragma segment Main
  2130. pascal
  2131. OSErr AppPropertyAccessor(    DescType        classWanted,            // Property class.
  2132.                               AEDesc*            container,                // Application.
  2133.                             DescType        containerClass, 
  2134.                             DescType        form,
  2135.                             AEDesc*            selectionData,
  2136.                             AEDesc*            resultToken,
  2137.                             long             theRefCon     )
  2138. {    
  2139.     #pragma unused (container,containerClass,theRefCon)
  2140.     DescType        propType;
  2141.     long            nilValue;
  2142.     
  2143.             //    Let's make sure we're accessing a valid descriptor type.
  2144.     if ((classWanted != cProperty) || (form != formPropertyID))
  2145.         return(errAEWrongDataType);
  2146.     nilValue = nil;        
  2147.     propType = *(LongPtr)*selectionData->dataHandle;            // Get the property type.
  2148.     return(AECreateDesc(propType, (Ptr)&nilValue, sizeof(long), resultToken)); 
  2149. }
  2150.  
  2151. //----------------------------------------------------------------------------------//
  2152. //    Returns the window with the given title if found.  Otherwise, nil is returned.    //
  2153. //    Use WindowList in order to find windows that may be invisible.                    //
  2154. //----------------------------------------------------------------------------------//
  2155. #pragma segment Main
  2156. WindowPtr GetWindowWithTitle( ConstStr255Param  titleToFind )
  2157. {
  2158.     WindowPeek    window;
  2159.     Str255        thisTitle;
  2160.     
  2161. #ifdef  THINK_C
  2162.     window = (WindowPeek)WindowList;    // WindowList finds invisible windows as well.
  2163. #else
  2164.     window = *(PeekPtr)WindowList;        // WindowList finds invisible windows as well.
  2165. #endif
  2166.     
  2167.     while (window)
  2168.     {
  2169.         GetWTitle((WindowPtr)window, thisTitle);
  2170.         if (EqualString(thisTitle, titleToFind, false, false))
  2171.             return((WindowPtr)window);
  2172.         window = window->nextWindow;
  2173.     }
  2174.     return(nil);
  2175. }
  2176.  
  2177. //----------------------------------------------------------------------------------//
  2178. //    Search all windows (including invisible), and return the window at the given     //
  2179. //    index if found. Otherwise, nil is returned. This routine also handles negative    //
  2180. //    indices which indicates that the offset    is from the end of the container.        //                                    //
  2181. //----------------------------------------------------------------------------------//
  2182. #pragma segment Main
  2183. WindowPtr GetWindowAtIndex(long  index)
  2184. {
  2185.     WindowPeek    window;
  2186.     short        count;
  2187.     
  2188.     index = index < 0 ? gNumWindowsOpen+index+1 : index;
  2189.     count = 1;
  2190.     
  2191. #ifdef  THINK_C
  2192.     window = (WindowPeek)WindowList;    // WindowList finds invisible windows as well.
  2193. #else
  2194.     window = *(PeekPtr)WindowList;        // WindowList finds invisible windows as well.
  2195. #endif
  2196.  
  2197.     while (window)
  2198.     {
  2199.         if (count == index)
  2200.             return((WindowPtr)window);
  2201.         window = window->nextWindow;
  2202.         count++;
  2203.     }
  2204.     return(nil);
  2205. }
  2206.  
  2207. //----------------------------------------------------------------------------------//
  2208. //    Returns the index number of the given window, where 1 is the frontmost.            //
  2209. //----------------------------------------------------------------------------------//
  2210. #pragma segment Main
  2211. long GetWindowIndexNum(WindowPtr myWindow)
  2212. {
  2213.     WindowPeek    thisWindow;
  2214.     long        index;
  2215.     
  2216. #ifdef  THINK_C
  2217.     thisWindow = (WindowPeek)WindowList;        // Compilers are so much fun!!.
  2218. #else
  2219.     thisWindow = *(PeekPtr)WindowList;            // WindowList finds invisible windows as well.
  2220. #endif
  2221.  
  2222.     index = 1;
  2223.     
  2224.     while (thisWindow)
  2225.     {
  2226.         if (thisWindow == (WindowPeek)myWindow)        // [pwpc]
  2227.             return(index);
  2228.         thisWindow = thisWindow->nextWindow;
  2229.         index++;
  2230.     }
  2231.     return(nil);
  2232. }
  2233.  
  2234. //----------------------------------------------------------------------------------//
  2235. //    This routine returns the bounds of a given window. Special calculations are        //
  2236. //    performed when the bounds is invalid (i.e., the window is hidden).                //
  2237. //----------------------------------------------------------------------------------//
  2238. #pragma segment Main
  2239. Rect GetWindowBounds(WindowPtr window)
  2240. {
  2241.     Rect    portRect, bitMapRect, bounds;
  2242.     
  2243.     bounds = (*((WindowPeek)window)->contRgn)->rgnBBox;        // check the content region.
  2244.     if (bounds.top == 0 && bounds.left == 0 &&
  2245.         bounds.bottom == 0 && bounds.right == 0)
  2246.     {
  2247.         portRect = window->portRect;
  2248.         bitMapRect = window->portBits.bounds;
  2249.         
  2250.         bounds.top =  portRect.top - bitMapRect.top;
  2251.         bounds.left = portRect.left - bitMapRect.left;
  2252.         bounds.bottom = portRect.bottom - bitMapRect.top;
  2253.         bounds.right = portRect.right - bitMapRect.left;
  2254.     }
  2255.     return(bounds);
  2256. }
  2257.  
  2258. //----------------------------------------------------------------------------------//
  2259. #pragma    segment Initialize
  2260. void InitAEHandlers()
  2261. {
  2262.     AEInstallEventHandler(kCoreEventClass,kAEOpenApplication,NewAEEventHandlerProc(HandleOpenApp), nil,false);
  2263.     AEInstallEventHandler(kCoreEventClass,kAEOpenDocuments,NewAEEventHandlerProc(DummyHandler), nil,false);
  2264.     AEInstallEventHandler(kCoreEventClass,kAEPrintDocuments,NewAEEventHandlerProc(DummyHandler), nil,false);
  2265.     AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, NewAEEventHandlerProc(HandleQuitApp), nil, false);
  2266.     AEInstallEventHandler(kAECoreSuite, kAEClone, NewAEEventHandlerProc(HandleClone), nil, false);
  2267.     AEInstallEventHandler(kAECoreSuite, kAEClose, NewAEEventHandlerProc(HandleClose), nil, false);
  2268.     AEInstallEventHandler(kAECoreSuite, kAECountElements, NewAEEventHandlerProc(HandleCountElements), nil, false);
  2269.     AEInstallEventHandler(kAECoreSuite, kAECreateElement, NewAEEventHandlerProc(HandleCreateElement), nil, false);
  2270.     AEInstallEventHandler(kAECoreSuite, kAEDelete, NewAEEventHandlerProc(HandleClose), nil, false);
  2271.     AEInstallEventHandler(kAECoreSuite, kAEDoObjectsExist, NewAEEventHandlerProc(HandleDoObjectsExist), nil, false);
  2272.     AEInstallEventHandler(kAECoreSuite, kAEGetData, NewAEEventHandlerProc(HandleGetData), kAEGetData, false);
  2273.     AEInstallEventHandler(kAECoreSuite, kAEGetDataSize, NewAEEventHandlerProc(HandleGetData), kAEGetDataSize, false);
  2274.     AEInstallEventHandler(kAECoreSuite, kAEGetClassInfo, NewAEEventHandlerProc(DummyHandler), nil, false);
  2275.     AEInstallEventHandler(kAECoreSuite, kAEGetEventInfo, NewAEEventHandlerProc(DummyHandler), nil, false);
  2276.     AEInstallEventHandler(kAECoreSuite, kAEMove, NewAEEventHandlerProc(HandleMove), nil, false);
  2277.     AEInstallEventHandler(kAECoreSuite, kAESave, NewAEEventHandlerProc(DummyHandler), nil, false);
  2278.     AEInstallEventHandler(kAECoreSuite, kAESetData, NewAEEventHandlerProc(HandleSetData), nil, false);
  2279.  
  2280.     AEObjectInit();
  2281.     AEInstallObjectAccessor(cWindow, typeNull, NewOSLAccessorProc(WindowAccessor), nil, false);
  2282.     AEInstallObjectAccessor(cProperty, typeNull, NewOSLAccessorProc(AppPropertyAccessor), nil, false);
  2283.     AEInstallObjectAccessor(cProperty, cWindow, NewOSLAccessorProc(WindowPropertyAccessor), nil, false);
  2284. }
  2285.